maverick-wave 4.9.4 → 4.11.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 (117) hide show
  1. package/.claude/skills/maverick-wave/SKILL.md +112 -12
  2. package/.claude/skills/maverick-wave/references/components.md +152 -4
  3. package/.claude/skills/maverick-wave/references/forms.md +26 -0
  4. package/.claude/skills/maverick-wave/references/javascript.md +34 -27
  5. package/.claude/skills/maverick-wave/references/layout.md +38 -3
  6. package/.claude/skills/maverick-wave/references/theming.md +33 -7
  7. package/CHANGELOG.md +6 -0
  8. package/README.md +79 -4
  9. package/index.html +16 -0
  10. package/maverick-wave.min.css +3 -3
  11. package/maverick-wave.min.js +1 -1
  12. package/package.json +2 -2
  13. package/src/js/main.js +71 -1
  14. package/src/partials/accordions-container.html +5 -0
  15. package/src/partials/alerts-container.html +5 -0
  16. package/src/partials/avatars-container.html +5 -0
  17. package/src/partials/badges-container.html +114 -0
  18. package/src/partials/blog-posts-container.html +5 -0
  19. package/src/partials/breadcrumbs-container.html +1 -1
  20. package/src/partials/button-bar-container.html +5 -0
  21. package/src/partials/buttons-container.html +84 -0
  22. package/src/partials/calendar-container.html +1 -1
  23. package/src/partials/cards-container.html +5 -0
  24. package/src/partials/code-container.html +6 -0
  25. package/src/partials/colors-container.html +1 -1
  26. package/src/partials/coming-soon-container.html +4 -0
  27. package/src/partials/divider-container.html +4 -0
  28. package/src/partials/dropdown-container.html +119 -0
  29. package/src/partials/empty-state-container.html +5 -0
  30. package/src/partials/form-container.html +5 -0
  31. package/src/partials/form-elements-container.html +5 -0
  32. package/src/partials/form-field-container.html +5 -0
  33. package/src/partials/gallery-container.html +5 -0
  34. package/src/partials/get-started-container.html +16 -4
  35. package/src/partials/header-container.html +6 -2
  36. package/src/partials/header-utilities-container.html +8 -2
  37. package/src/partials/html-lists-container.html +5 -0
  38. package/src/partials/info-container.html +4 -0
  39. package/src/partials/input-group-container.html +5 -0
  40. package/src/partials/item-lists-container.html +5 -0
  41. package/src/partials/kanban-container.html +1 -1
  42. package/src/partials/kbd-container.html +63 -0
  43. package/src/partials/meta-info-container.html +5 -0
  44. package/src/partials/pagination-container.html +1 -1
  45. package/src/partials/panels-container.html +4 -0
  46. package/src/partials/progress-container.html +4 -0
  47. package/src/partials/ratings-container.html +1 -1
  48. package/src/partials/skeleton-container.html +5 -0
  49. package/src/partials/spinners-container.html +5 -1
  50. package/src/partials/stepper-container.html +4 -0
  51. package/src/partials/tables-container.html +7 -0
  52. package/src/partials/tabs-container.html +35 -13
  53. package/src/partials/tags-container.html +5 -0
  54. package/src/partials/tiles-container.html +1 -1
  55. package/src/partials/typography-container.html +5 -0
  56. package/src/partials/utilities-container.html +153 -0
  57. package/src/scss/abstracts/_mixins.scss +176 -0
  58. package/src/scss/abstracts/_variables.scss +193 -5
  59. package/src/scss/base/_base.scss +103 -2
  60. package/src/scss/base/_reset.scss +43 -1
  61. package/src/scss/base/_typography.scss +47 -0
  62. package/src/scss/components/_accordions.scss +11 -1
  63. package/src/scss/components/_alerts.scss +3 -3
  64. package/src/scss/components/_avatars.scss +27 -6
  65. package/src/scss/components/_badge.scss +157 -0
  66. package/src/scss/components/_blog-post.scss +10 -7
  67. package/src/scss/components/_breadcrumbs.scss +11 -2
  68. package/src/scss/components/_button-bar.scss +9 -2
  69. package/src/scss/components/_buttons.scss +133 -17
  70. package/src/scss/components/_calendar.scss +13 -2
  71. package/src/scss/components/_cards.scss +12 -5
  72. package/src/scss/components/_code.scss +15 -0
  73. package/src/scss/components/_coming-soon.scss +5 -2
  74. package/src/scss/components/_content-slider.scss +1 -1
  75. package/src/scss/components/_dropdown.scss +219 -0
  76. package/src/scss/components/_gallery.scss +17 -8
  77. package/src/scss/components/_index.scss +3 -0
  78. package/src/scss/components/_info.scss +14 -8
  79. package/src/scss/components/_kanban.scss +40 -6
  80. package/src/scss/components/_kbd.scss +43 -0
  81. package/src/scss/components/_lists.scss +26 -23
  82. package/src/scss/components/_modals.scss +71 -6
  83. package/src/scss/components/_pagination.scss +4 -3
  84. package/src/scss/components/_panels.scss +13 -14
  85. package/src/scss/components/_progress.scss +1 -1
  86. package/src/scss/components/_segmented.scss +8 -4
  87. package/src/scss/components/_stepper.scss +3 -3
  88. package/src/scss/components/_tables.scss +5 -8
  89. package/src/scss/components/_tabs.scss +22 -3
  90. package/src/scss/components/_tags.scss +1 -2
  91. package/src/scss/components/_techstack-bucket.scss +8 -5
  92. package/src/scss/components/_theme-toggle.scss +16 -8
  93. package/src/scss/components/_tiles.scss +14 -4
  94. package/src/scss/components/_timelines.scss +9 -6
  95. package/src/scss/components/_toasts.scss +1 -1
  96. package/src/scss/form-elements/_checkbox.scss +2 -1
  97. package/src/scss/form-elements/_form.scss +2 -2
  98. package/src/scss/form-elements/_input-group.scss +30 -1
  99. package/src/scss/form-elements/_input.scss +10 -10
  100. package/src/scss/form-elements/_login.scss +1 -1
  101. package/src/scss/form-elements/_radio.scss +4 -3
  102. package/src/scss/form-elements/_select.scss +9 -10
  103. package/src/scss/form-elements/_slider.scss +11 -11
  104. package/src/scss/form-elements/_textarea.scss +5 -8
  105. package/src/scss/form-elements/_toggle.scss +6 -5
  106. package/src/scss/layout/_footer.scss +14 -7
  107. package/src/scss/layout/_header.scss +18 -17
  108. package/src/scss/layout/_home.scss +1 -1
  109. package/src/scss/layout/_main.scss +6 -6
  110. package/src/scss/layout/_section.scss +7 -4
  111. package/src/scss/utilities/_accessibility.scss +38 -0
  112. package/src/scss/utilities/_aspect.scss +27 -0
  113. package/src/scss/utilities/_display.scss +52 -0
  114. package/src/scss/utilities/_elevation.scss +16 -0
  115. package/src/scss/utilities/_index.scss +2 -0
  116. package/src/scss/utilities/_text.scss +63 -0
  117. package/src/scss/utilities/_touch-targets.scss +63 -0
@@ -36,8 +36,58 @@ $_active-prefix: 'dark';
36
36
  --mw-light-#{$name}: #{$value};
37
37
  }
38
38
 
39
- // Transitions
40
- --mw-transition: #{$transition-default};
39
+ // Motion. The scale itself lives in the variables file - these are the knobs
40
+ // a project retunes without recompiling.
41
+ --mw-duration-instant: #{$duration-instant};
42
+ --mw-duration-fast: #{$duration-fast};
43
+ --mw-duration-base: #{$duration-base};
44
+ --mw-duration-slow: #{$duration-slow};
45
+ --mw-duration-slower: #{$duration-slower};
46
+ --mw-duration-zoom: #{$duration-zoom};
47
+ --mw-ease-out: #{$ease-out};
48
+ --mw-ease-in-out: #{$ease-in-out};
49
+ --mw-ease-spring: #{$ease-spring};
50
+
51
+ // The workhorse: every hover, focus and active state in the framework. An
52
+ // explicit property list rather than `all` - see $transition-properties.
53
+ --mw-transition: #{$transition-properties} var(--mw-duration-base)
54
+ var(--mw-ease-out);
55
+ // Same list, for a state change that should feel instant under the pointer
56
+ // rather than animated - a button label, a tag, a table row.
57
+ --mw-transition-fast: #{$transition-properties} var(--mw-duration-fast)
58
+ var(--mw-ease-out);
59
+
60
+ // Control sizes - see the note in the variables file. Custom properties
61
+ // rather than compile-time only, so an application can tighten its forms
62
+ // without recompiling the framework.
63
+ --mw-control-height-sm: #{$control-height-sm};
64
+ --mw-control-height: #{$control-height};
65
+ --mw-control-height-lg: #{$control-height-lg};
66
+ --mw-control-font-sm: #{$control-font-sm};
67
+ --mw-control-font: #{$control-font};
68
+ --mw-control-font-lg: #{$control-font-lg};
69
+ --mw-control-line-height: #{$control-line-height};
70
+
71
+ // Focus ring
72
+ --mw-focus-ring-width: #{$focus-ring-width};
73
+ --mw-focus-ring-offset: #{$focus-ring-offset};
74
+ --mw-focus-ring-color: var(--mw-primary-text-color);
75
+ --mw-focus-halo-size: #{$focus-halo-size};
76
+ --mw-focus-halo-opacity: #{$focus-halo-opacity};
77
+
78
+ // Tells the browser which way round the page is, which is the only way the
79
+ // chrome it draws itself follows along: scrollbars, the popup a <select>
80
+ // opens, the panel behind a date picker, the spinner on a number field.
81
+ // Without it a dark page keeps light scrollbars and a white select popup.
82
+ @if $mw-theme-mode == 'light' {
83
+ color-scheme: light;
84
+ } @else {
85
+ color-scheme: dark;
86
+ }
87
+ // Native controls the framework does not paint over - <progress>, a file
88
+ // input's button, a text selection handle - take the brand colour instead of
89
+ // the OS blue.
90
+ accent-color: var(--mw-primary-color);
41
91
 
42
92
  // theme for theme-toggle
43
93
  --mw-internal-theme-mode: #{$mw-theme-mode};
@@ -87,9 +137,25 @@ $_active-prefix: 'dark';
87
137
  @each $name, $value in $light-theme-colors {
88
138
  --mw-#{$name}: var(--mw-light-#{$name});
89
139
  }
140
+
141
+ color-scheme: light;
90
142
  }
91
143
  }
92
144
 
145
+ // Form controls are deliberately light in both themes - see
146
+ // $form-elements-background - so they opt back out of the page's colour scheme.
147
+ // Without this the browser draws their built-in parts for a dark surface and a
148
+ // date field ends up with a white calendar icon on a near-white background.
149
+ input,
150
+ select,
151
+ textarea,
152
+ .mw-input,
153
+ .mw-select,
154
+ .mw-textarea,
155
+ .mw-input-group {
156
+ color-scheme: light;
157
+ }
158
+
93
159
  // Anything that draws its own surface re-points the cover colour of a scroll
94
160
  // hint, so a tab bar or a wide table inside a card fades into the card and not
95
161
  // into the page behind it. Inherited, so nesting keeps working.
@@ -100,3 +166,38 @@ $_active-prefix: 'dark';
100
166
  .mw-calendar:not(.mw-calendar-plain) {
101
167
  --mw-scroll-hint-cover: var(--mw-card-background);
102
168
  }
169
+
170
+ // ---------------------------------------------------------------------------
171
+ // Reduced motion
172
+ //
173
+ // One switch for the whole framework. Turning the duration tokens down covers
174
+ // everything built on them; the blanket rule underneath covers the handful of
175
+ // animations that name their own timing, plus anything a project wrote itself.
176
+ //
177
+ // 1ms and not 0: a zero-length transition never fires transitionend, and any
178
+ // script waiting for it to clean up - a modal removing a class, a toast
179
+ // removing itself - would wait forever.
180
+ // ---------------------------------------------------------------------------
181
+ @media (prefers-reduced-motion: reduce) {
182
+ :root {
183
+ --mw-duration-instant: 1ms;
184
+ --mw-duration-fast: 1ms;
185
+ --mw-duration-base: 1ms;
186
+ --mw-duration-slow: 1ms;
187
+ --mw-duration-slower: 1ms;
188
+ }
189
+
190
+ *,
191
+ *::before,
192
+ *::after {
193
+ animation-duration: 1ms !important;
194
+ animation-delay: 0ms !important;
195
+ animation-iteration-count: 1 !important;
196
+ transition-duration: 1ms !important;
197
+ transition-delay: 0ms !important;
198
+ }
199
+
200
+ html {
201
+ scroll-behavior: auto;
202
+ }
203
+ }
@@ -15,10 +15,14 @@ html {
15
15
  scroll-padding-top: calc(var(--mw-header-height) + #{spacing('4')});
16
16
  -webkit-text-size-adjust: 100%;
17
17
  text-size-adjust: 100%;
18
+ @include scrollbar(var(--mw-border), transparent);
18
19
  }
19
20
 
20
21
  body {
21
22
  background: var(--mw-page-background);
23
+ overflow-wrap: break-word;
24
+ -webkit-font-smoothing: antialiased;
25
+ -moz-osx-font-smoothing: grayscale;
22
26
 
23
27
  &:has(.mw-modal-open) {
24
28
  overflow: hidden;
@@ -26,10 +30,20 @@ body {
26
30
  }
27
31
  }
28
32
 
33
+ // A selection in the browser default blue on a deep blue page is the one bit of
34
+ // chrome that gives away that nobody looked. Brand tint, kept translucent so it
35
+ // works over a card, a code block and an image caption alike.
36
+ ::selection {
37
+ background: color-mix(in srgb, var(--mw-primary-color) 55%, transparent);
38
+ color: var(--mw-text-color);
39
+ }
40
+
29
41
  a {
30
42
  text-decoration: none;
31
43
  color: var(--mw-text-muted-color);
32
44
  transition: var(--mw-transition);
45
+ @include tappable;
46
+ @include focus-ring(2px);
33
47
  }
34
48
 
35
49
  ul {
@@ -39,6 +53,9 @@ ul {
39
53
  hr {
40
54
  margin: spacing('3') 0;
41
55
  color: var(--mw-text-muted-color);
56
+ border: 0;
57
+ border-top: 1px solid currentcolor;
58
+ opacity: 0.35;
42
59
  }
43
60
 
44
61
  img {
@@ -52,13 +69,38 @@ button {
52
69
  border: none;
53
70
  cursor: pointer;
54
71
  font-family: inherit;
72
+ color: inherit;
73
+ @include tappable;
55
74
  }
56
75
 
57
76
  input,
58
- textarea {
77
+ textarea,
78
+ select {
59
79
  font-family: inherit;
60
80
  }
61
81
 
82
+ // A control the framework has no component for - a bare <summary>, a
83
+ // contenteditable, an element carrying tabindex - still gets a ring.
84
+ :focus-visible {
85
+ outline: var(--mw-focus-ring-width) solid var(--mw-focus-ring-color);
86
+ outline-offset: var(--mw-focus-ring-offset);
87
+ }
88
+
89
+ // Media that has to fit its box without distorting. `height: auto` alone keeps
90
+ // the aspect ratio only while nothing else sets a height.
91
+ img,
92
+ svg,
93
+ video,
94
+ canvas {
95
+ max-width: 100%;
96
+ }
97
+
98
+ // Anchored headings clear the fixed bar the same way html's scroll-padding does,
99
+ // for the case where a script scrolls an element into view itself.
100
+ :target {
101
+ scroll-margin-top: calc(var(--mw-header-height) + #{spacing('4')});
102
+ }
103
+
62
104
  table {
63
105
  border-collapse: collapse;
64
106
  width: 100%;
@@ -25,6 +25,22 @@ h6 {
25
25
  line-height: 1.2;
26
26
  margin-bottom: spacing('4');
27
27
  font-weight: font-weight('bold');
28
+ text-wrap: balance;
29
+ overflow-wrap: break-word;
30
+ }
31
+
32
+ // Tracking
33
+ h1 {
34
+ letter-spacing: -0.025em;
35
+ }
36
+
37
+ h2 {
38
+ letter-spacing: -0.02em;
39
+ }
40
+
41
+ h3,
42
+ h4 {
43
+ letter-spacing: -0.01em;
28
44
  }
29
45
 
30
46
  // Two steps, not one. With the single jump at 576px, everything between there
@@ -79,6 +95,37 @@ h6 {
79
95
  // Paragraphs
80
96
  p {
81
97
  margin-bottom: spacing('3');
98
+ text-wrap: pretty;
99
+ }
100
+
101
+ // Inline text the framework was leaving to the browser. `small` in particular
102
+ // showed up in footers and captions at whatever the UA felt like.
103
+ small {
104
+ font-size: font-size('sm');
105
+ color: var(--mw-text-muted-color);
106
+ }
107
+
108
+ strong,
109
+ b {
110
+ font-weight: font-weight('bold');
111
+ }
112
+
113
+ // The browser's own is a solid block of background with the text left dark on
114
+ // it - unreadable on a dark page. Tinted with the brand instead, and it keeps
115
+ // the theme's ink.
116
+ mark {
117
+ background: color-mix(in srgb, var(--mw-warning-color) 35%, transparent);
118
+ color: inherit;
119
+ padding: 0.1em 0.25em;
120
+ border-radius: radius('xs');
121
+ }
122
+
123
+ // Underlined in the same shape the link buttons use, so an inline link and a
124
+ // `mw-btn-link` do not read as two different things
125
+ abbr[title] {
126
+ text-decoration: underline dotted;
127
+ text-underline-offset: 0.2em;
128
+ cursor: help;
82
129
  }
83
130
 
84
131
  // Code elements
@@ -18,6 +18,16 @@
18
18
  padding: spacing('4');
19
19
  background: var(--mw-card-background);
20
20
  cursor: pointer;
21
+ @include tappable;
22
+ @include focus-ring(-2px);
23
+
24
+ // A press has to be felt. On touch it is the only feedback there is - a
25
+ // finger never hovers - and every clickable surface in the framework owes it.
26
+ &:active {
27
+ background: var(--mw-primary-background);
28
+ transition-duration: var(--mw-duration-instant);
29
+ }
30
+
21
31
  display: flex;
22
32
  justify-content: space-between;
23
33
  align-items: center;
@@ -56,7 +66,7 @@
56
66
  &-content {
57
67
  height: spacing('0');
58
68
  overflow: hidden;
59
- transition: height 0.9s ease;
69
+ transition: height var(--mw-duration-slower) var(--mw-ease-out);
60
70
  background: var(--mw-card-background);
61
71
  interpolate-size: allow-keywords;
62
72
 
@@ -10,7 +10,7 @@
10
10
 
11
11
  background: var(--mw-card-background);
12
12
  border: 1px solid var(--mw-border);
13
- box-shadow: 0 2px 5px var(--mw-shadow);
13
+ box-shadow: var(--mw-elevation-2);
14
14
 
15
15
  &-icon {
16
16
  flex-shrink: 0;
@@ -49,9 +49,9 @@
49
49
  }
50
50
 
51
51
  @include media-down('sm') {
52
- padding: spacing('2');
52
+ padding: spacing('4');
53
53
  &-icon {
54
- margin-right: spacing('2');
54
+ margin-right: spacing('3');
55
55
  }
56
56
  }
57
57
  }
@@ -12,10 +12,10 @@ $_mw-avatar-colors: (
12
12
  .mw-avatar {
13
13
  display: inline-flex;
14
14
  position: relative;
15
- border-radius: 50%;
15
+ border-radius: radius('full');
16
16
  overflow: hidden;
17
17
  border: 3px solid var(--mw-border);
18
- box-shadow: 0 6px 15px var(--mw-shadow);
18
+ box-shadow: var(--mw-elevation-3);
19
19
  margin: spacing('1');
20
20
 
21
21
  // Standard (md)
@@ -89,14 +89,14 @@ $_mw-avatar-colors: (
89
89
  flex-wrap: wrap; // Allow items to wrap to next line
90
90
  justify-content: flex-start;
91
91
  margin: spacing('2');
92
+ row-gap: spacing('3');
92
93
 
93
94
  .mw-avatar {
94
- margin-right: -15px;
95
- margin-bottom: -15px;
95
+ margin: spacing('0') -15px spacing('0') spacing('0');
96
96
  border: 2px solid var(--mw-secondary-text-color);
97
- transition: transform 0.3s ease;
97
+ transition: transform var(--mw-duration-base) var(--mw-ease-out);
98
98
 
99
- &:hover {
99
+ @include hover {
100
100
  transform: translateY(-3px);
101
101
  z-index: z-index('lift');
102
102
  }
@@ -115,11 +115,32 @@ $_mw-avatar-colors: (
115
115
  margin-right: -20px;
116
116
  }
117
117
 
118
+ .mw-avatar-xs {
119
+ margin-right: -5px;
120
+ }
121
+ .mw-avatar-sm {
122
+ margin-right: -10px;
123
+ }
124
+ .mw-avatar-lg {
125
+ margin-right: -23px;
126
+ }
127
+ .mw-avatar-xl {
128
+ margin-right: -40px;
129
+ }
130
+
131
+ .mw-avatar:last-child {
132
+ margin-right: spacing('0');
133
+ }
134
+
118
135
  @include media-down('sm') {
119
136
  // For small screens, create a more compact layout
120
137
  .mw-avatar {
121
138
  margin-right: -10px; // Reduce overlap on small screens
122
139
  }
140
+
141
+ .mw-avatar:last-child {
142
+ margin-right: spacing('0');
143
+ }
123
144
  }
124
145
  }
125
146
 
@@ -0,0 +1,157 @@
1
+ @use '../abstracts' as *;
2
+
3
+ // Badge
4
+ //
5
+ // Not a tag. A tag is a label with a soft surface that names something - a
6
+ // topic, a state, a category - and sits in a row of its own kind. A badge is a
7
+ // solid mark that carries a *count* or a *status*, and it usually sits on
8
+ // something else: the number on a bell, the dot on an avatar, the "3" on a tab.
9
+
10
+ $_mw-badge-colors: (primary, secondary, success, warning, danger, info);
11
+
12
+ .mw-badge {
13
+ display: inline-flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ min-width: 1.25rem;
17
+ height: 1.25rem;
18
+ padding: 0 spacing('2');
19
+ border-radius: radius('xl');
20
+ background: var(--mw-primary-color);
21
+ color: var(--mw-primary-accent-text-color);
22
+ font-size: font-size('2xs');
23
+ font-weight: font-weight('bold');
24
+ line-height: 1;
25
+ font-variant-numeric: tabular-nums lining-nums;
26
+ white-space: nowrap;
27
+ vertical-align: middle;
28
+ }
29
+
30
+ @each $name in $_mw-badge-colors {
31
+ .mw-badge-#{$name} {
32
+ background: var(--mw-#{$name}-color);
33
+ color: var(--mw-#{$name}-accent-text-color);
34
+ }
35
+ }
36
+
37
+ .mw-badge-muted {
38
+ background: var(--mw-gray-color);
39
+ color: var(--mw-accent-text-color);
40
+ }
41
+
42
+ .mw-badge-outline {
43
+ background: transparent;
44
+ border: 1px solid currentcolor;
45
+ color: var(--mw-primary-text-color);
46
+ }
47
+
48
+ .mw-badge-sm {
49
+ min-width: 1rem;
50
+ height: 1rem;
51
+ padding: 0 spacing('1');
52
+ font-size: font-size('3xs');
53
+ }
54
+
55
+ .mw-badge-lg {
56
+ min-width: 1.6rem;
57
+ height: 1.6rem;
58
+ padding: 0 spacing('3');
59
+ font-size: font-size('xs');
60
+ }
61
+
62
+ // Dot
63
+ .mw-badge-dot {
64
+ display: inline-block;
65
+ width: 0.55rem;
66
+ height: 0.55rem;
67
+ min-width: 0;
68
+ padding: 0;
69
+ border-radius: radius('full');
70
+ background: var(--mw-primary-color);
71
+ flex-shrink: 0;
72
+ vertical-align: middle;
73
+ }
74
+
75
+ // A dot that is actually live - a running job, an open connection. The ring
76
+ // pulses outward and fades; the dot underneath never moves, so a row of them
77
+ // stays legible.
78
+ .mw-badge-pulse {
79
+ position: relative;
80
+
81
+ &::after {
82
+ content: '';
83
+ position: absolute;
84
+ inset: 0;
85
+ border-radius: inherit;
86
+ background: inherit;
87
+ animation: mw-badge-pulse 1.8s var(--mw-ease-out) infinite;
88
+ }
89
+ }
90
+
91
+ @keyframes mw-badge-pulse {
92
+ 0% {
93
+ transform: scale(1);
94
+ opacity: 0.7;
95
+ }
96
+ 100% {
97
+ transform: scale(2.6);
98
+ opacity: 0;
99
+ }
100
+ }
101
+
102
+ // Anchoring a badge to something
103
+ .mw-badge-anchor {
104
+ position: relative;
105
+ display: inline-flex;
106
+ }
107
+
108
+ .mw-badge-float {
109
+ position: absolute;
110
+ top: 0;
111
+ right: 0;
112
+ transform: translate(40%, -40%);
113
+ box-shadow: 0 0 0 2px var(--mw-page-background);
114
+ pointer-events: none;
115
+ z-index: z-index('lift');
116
+ }
117
+
118
+ // Inside anything that paints its own surface the ring has to match that
119
+ // surface, not the page
120
+ .mw-card,
121
+ .mw-panel,
122
+ .mw-modal,
123
+ .mw-tile,
124
+ .mw-header {
125
+ .mw-badge-float {
126
+ box-shadow: 0 0 0 2px var(--mw-card-background);
127
+ }
128
+ }
129
+
130
+ .mw-header .mw-badge-float {
131
+ box-shadow: 0 0 0 2px var(--mw-header-background);
132
+ }
133
+
134
+ // Status line
135
+ .mw-badge-status {
136
+ display: inline-flex;
137
+ align-items: center;
138
+ gap: spacing('2');
139
+ font-size: font-size('sm');
140
+ color: var(--mw-text-color);
141
+ white-space: nowrap;
142
+ }
143
+
144
+ @each $name in $_mw-badge-colors {
145
+ .mw-badge-dot-#{$name} {
146
+ background: var(--mw-#{$name}-color);
147
+ }
148
+
149
+ .mw-badge-status-#{$name} .mw-badge-dot {
150
+ background: var(--mw-#{$name}-color);
151
+ }
152
+ }
153
+
154
+ .mw-badge-dot-muted,
155
+ .mw-badge-status-muted .mw-badge-dot {
156
+ background: var(--mw-gray-color);
157
+ }
@@ -4,7 +4,10 @@
4
4
  position: relative;
5
5
  margin: spacing('2');
6
6
  padding: spacing('4') spacing('7');
7
- animation: pageReveal 1.6s ease-out forwards;
7
+ // One-shot entrance, not a loop, so it belongs on the scale. It ran for
8
+ // 1.6s before - long enough that the reader is into the second paragraph
9
+ // while the page is still arriving.
10
+ animation: pageReveal var(--mw-duration-slower) var(--mw-ease-out) forwards;
8
11
  border-radius: radius('sm') radius('2xl') radius('sm') radius('2xl');
9
12
  box-shadow:
10
13
  var(--mw-border) 0 30px 60px -18px inset,
@@ -34,8 +37,8 @@
34
37
  position: absolute;
35
38
  left: 1px;
36
39
  top: 1px;
40
+ bottom: 1px;
37
41
  width: 7px;
38
- height: 99%;
39
42
  background: linear-gradient(
40
43
  to bottom,
41
44
  var(--mw-primary-color),
@@ -76,8 +79,8 @@
76
79
  justify-content: center;
77
80
  margin-bottom: spacing('4');
78
81
  font-size: font-size('xl');
79
- box-shadow: 0 5px 9px var(--mw-shadow);
80
- animation: iconFlip 2s ease-out forwards;
82
+ box-shadow: var(--mw-elevation-2);
83
+ animation: iconFlip var(--mw-duration-slower) var(--mw-ease-out) forwards;
81
84
 
82
85
  @keyframes iconFlip {
83
86
  0% {
@@ -131,7 +134,7 @@
131
134
  object-fit: contain;
132
135
  border-radius: radius('sm');
133
136
  margin-bottom: spacing('5');
134
- box-shadow: 0 5px 12px var(--mw-shadow);
137
+ box-shadow: var(--mw-elevation-3);
135
138
  }
136
139
 
137
140
  // Content section
@@ -198,8 +201,8 @@
198
201
  transform: scaleX(1);
199
202
  transform-origin: left;
200
203
  transition:
201
- transform 0.2s ease,
202
- opacity 0.2s ease;
204
+ transform var(--mw-duration-fast) var(--mw-ease-out),
205
+ opacity var(--mw-duration-fast) var(--mw-ease-out);
203
206
  }
204
207
 
205
208
  &:hover {
@@ -47,15 +47,24 @@
47
47
  position: relative;
48
48
  transition: var(--mw-transition);
49
49
 
50
+ @include tappable;
51
+
50
52
  &:hover,
51
- &:focus,
52
53
  &.mw-breadcrumbs-active {
53
- outline: 0;
54
54
  color: var(--mw-primary-text-color);
55
55
  border-color: var(--mw-primary-text-color);
56
56
  z-index: z-index('lift');
57
57
  }
58
58
 
59
+ &:active {
60
+ color: var(--mw-primary-text-color);
61
+ transition-duration: var(--mw-duration-instant);
62
+ }
63
+
64
+ @include focus-ring-inset(-4px) {
65
+ z-index: z-index('lift');
66
+ }
67
+
59
68
  // Counter-skew the content
60
69
  & > * {
61
70
  transform: skew(30deg);
@@ -20,8 +20,8 @@
20
20
  gap: spacing('2');
21
21
 
22
22
  .mw-btn {
23
- width: 96%;
24
- min-width: 200px;
23
+ width: 100%;
24
+ min-width: 0;
25
25
  }
26
26
  }
27
27
  }
@@ -57,6 +57,8 @@
57
57
  background: var(--mw-primary-color);
58
58
  color: var(--mw-primary-accent-text-color);
59
59
 
60
+ @include btn-solid;
61
+
60
62
  &:hover:not(:disabled) {
61
63
  background: var(--mw-primary-color-hover);
62
64
  }
@@ -71,6 +73,8 @@
71
73
  background: var(--mw-secondary-color);
72
74
  color: var(--mw-secondary-accent-text-color);
73
75
 
76
+ @include btn-solid;
77
+
74
78
  &:hover:not(:disabled) {
75
79
  background: var(--mw-secondary-color-hover);
76
80
  }
@@ -115,6 +119,8 @@
115
119
  background: var(--mw-primary-color);
116
120
  color: var(--mw-primary-accent-text-color);
117
121
 
122
+ @include btn-solid;
123
+
118
124
  &:hover:not(:disabled) {
119
125
  background: var(--mw-primary-color-hover);
120
126
  }
@@ -137,6 +143,7 @@
137
143
  .mw-btn {
138
144
  padding: spacing('3') spacing('5');
139
145
  font-size: font-size('md');
146
+ min-height: var(--mw-control-height-lg);
140
147
  }
141
148
 
142
149
  @include media-down('sm') {