maverick-wave 5.22.0 → 5.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/mw-maverick-wave/SKILL.md +15 -7
- package/.claude/skills/mw-maverick-wave/examples/static-landing-page.md +22 -14
- package/.claude/skills/mw-maverick-wave/references/components.md +123 -11
- package/.claude/skills/mw-maverick-wave/references/layout.md +35 -5
- package/.claude/skills/mw-maverick-wave/references/theming.md +5 -0
- package/CHANGELOG.md +14 -0
- package/README.md +2 -2
- package/index.html +80 -38
- package/maverick-wave.min.css +4 -4
- package/package.json +2 -2
- package/src/partials/contact-container.html +85 -0
- package/src/partials/documentation-container.html +3 -0
- package/src/partials/highlights-container.html +7 -5
- package/src/partials/leader-row-container.html +139 -0
- package/src/partials/lunch-menu-container.html +341 -0
- package/src/partials/page-header-container.html +2 -2
- package/src/partials/section-head-container.html +74 -0
- package/src/scss/abstracts/_functions.scss +38 -7
- package/src/scss/base/_base.scss +6 -1
- package/src/scss/components/_contact.scss +29 -0
- package/src/scss/components/_date-stamp.scss +141 -0
- package/src/scss/components/_index.scss +3 -0
- package/src/scss/components/_leader-row.scss +89 -0
- package/src/scss/components/_pricing.scss +4 -0
- package/src/scss/layout/_grid.scss +6 -0
- package/src/scss/layout/_main.scss +19 -0
- package/src/scss/layout/_section.scss +114 -44
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<h3 class="mw-section-subtitle">Section Head</h3>
|
|
2
|
+
|
|
3
|
+
<p class="mw-text-muted mw-mb-6">
|
|
4
|
+
The opening of a section: a hairline rule, a mark sitting on its left end, the
|
|
5
|
+
title, and the line that says what follows. Everything starts at one edge -
|
|
6
|
+
centred body copy moves its own left edge with every line break, so the eye
|
|
7
|
+
has to find the start of each line instead of jumping to a fixed position.
|
|
8
|
+
Fine for a heading, tiring from the third line on.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<div class="mw-grid-1">
|
|
12
|
+
<div>
|
|
13
|
+
<h3 class="mw-mb-4">Title, Lead and Mark</h3>
|
|
14
|
+
<div class="mw-card mw-card-simple">
|
|
15
|
+
<div class="mw-section-head">
|
|
16
|
+
<h2 class="mw-section-head-title">Foundations</h2>
|
|
17
|
+
<p class="mw-section-head-intro">
|
|
18
|
+
The raw material - type, color, spacing and the small utilities
|
|
19
|
+
everything else is built from. The lead stops at 65 characters, or at
|
|
20
|
+
four fifths of the container, whichever comes first.
|
|
21
|
+
</p>
|
|
22
|
+
</div>
|
|
23
|
+
<p class="mw-mb-0">The content of the section starts here.</p>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div>
|
|
28
|
+
<h3 class="mw-mb-4">Numbered</h3>
|
|
29
|
+
<p class="mw-text-muted mw-mb-4">
|
|
30
|
+
<code>mw-section-head-numbered</code> counts in the browser, so no page
|
|
31
|
+
keeps its own running order in the markup. The number closes the rule the
|
|
32
|
+
mark opens, and the counter restarts per <code>mw-main</code>. Opt-in: a
|
|
33
|
+
single section on a legal page numbered "01" is noise.
|
|
34
|
+
</p>
|
|
35
|
+
<div class="mw-card mw-card-simple">
|
|
36
|
+
<div class="mw-section-head mw-section-head-numbered">
|
|
37
|
+
<h2 class="mw-section-head-title">About me</h2>
|
|
38
|
+
<p class="mw-section-head-intro">
|
|
39
|
+
A section head without a lead works the same way - the next one below
|
|
40
|
+
shows it.
|
|
41
|
+
</p>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="mw-section-head mw-section-head-numbered">
|
|
45
|
+
<h2 class="mw-section-head-title">Contact</h2>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div>
|
|
51
|
+
<h3 class="mw-mb-4">Colored Mark</h3>
|
|
52
|
+
<p class="mw-text-muted mw-mb-4">
|
|
53
|
+
The mark is the one colored thing in the head, so it is where a section
|
|
54
|
+
picks up a tone: <code>mw-section-head-secondary</code>,
|
|
55
|
+
<code>-success</code>, <code>-warning</code>, <code>-danger</code> and
|
|
56
|
+
<code>-info</code>. Its length is
|
|
57
|
+
<code>--mw-section-head-mark-width</code> (80px), the gap to the content
|
|
58
|
+
below <code>--mw-section-head-gap</code>.
|
|
59
|
+
</p>
|
|
60
|
+
<div class="mw-card mw-card-simple">
|
|
61
|
+
<div class="mw-section-head mw-section-head-secondary">
|
|
62
|
+
<h2 class="mw-section-head-title">Secondary</h2>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="mw-section-head mw-section-head-danger">
|
|
66
|
+
<h2 class="mw-section-head-title">Danger</h2>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<div class="mw-section-head mw-section-head-success">
|
|
70
|
+
<h2 class="mw-section-head-title">Success</h2>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
@@ -23,17 +23,48 @@
|
|
|
23
23
|
// Only the slope is in vw: a size in vw alone ignores the reader's font size and
|
|
24
24
|
// stops responding to zoom, the rem term is what keeps that alive.
|
|
25
25
|
@function fluid($min, $max, $from: 'xs', $to: 'md') {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
@return _ramp(
|
|
27
|
+
_to-rem($min, 'min'),
|
|
28
|
+
_to-rem($max, 'max'),
|
|
29
|
+
math.div(map.get(v.$breakpoints, $from), 16px),
|
|
30
|
+
math.div(map.get(v.$breakpoints, $to), 16px),
|
|
31
|
+
vw
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// The same ramp against the container instead of the viewport. For anything
|
|
36
|
+
// inside a `@container` block: sizing there off vw means a 440px card on a
|
|
37
|
+
// 1400px screen takes the width a 900px card was measured for, which is the
|
|
38
|
+
// mismatch container queries exist to remove. The endpoints are container
|
|
39
|
+
// widths rather than breakpoint names, because a container has no breakpoints.
|
|
40
|
+
@function fluid-container($min, $max, $from, $to) {
|
|
41
|
+
$from-rem: _to-rem($from, 'from');
|
|
42
|
+
$to-rem: _to-rem($to, 'to');
|
|
43
|
+
|
|
44
|
+
@if $from-rem == $to-rem {
|
|
45
|
+
@error "fluid-container(): $from and $to must differ, both are #{$from}.";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@return _ramp(
|
|
49
|
+
_to-rem($min, 'min'),
|
|
50
|
+
_to-rem($max, 'max'),
|
|
51
|
+
$from-rem,
|
|
52
|
+
$to-rem,
|
|
53
|
+
cqi
|
|
54
|
+
);
|
|
55
|
+
}
|
|
30
56
|
|
|
31
|
-
|
|
32
|
-
|
|
57
|
+
// Both of the above draw the same line through (from, min) and (to, max) and
|
|
58
|
+
// disagree only on what measures the axis. Shared so a change to the rem term -
|
|
59
|
+
// the part that keeps the size responding to zoom - cannot reach one and miss
|
|
60
|
+
// the other.
|
|
61
|
+
@function _ramp($min-rem, $max-rem, $from-rem, $to-rem, $unit) {
|
|
62
|
+
$slope: math.div($max-rem - $min-rem, $to-rem - $from-rem);
|
|
63
|
+
$intercept: $min-rem - $slope * $from-rem;
|
|
33
64
|
|
|
34
65
|
@return clamp(
|
|
35
66
|
#{$min-rem}rem,
|
|
36
|
-
#{_round4($intercept)}rem + #{_round4($slope * 100)}
|
|
67
|
+
#{_round4($intercept)}rem + #{_round4($slope * 100)}#{$unit},
|
|
37
68
|
#{$max-rem}rem
|
|
38
69
|
);
|
|
39
70
|
}
|
package/src/scss/base/_base.scss
CHANGED
|
@@ -159,7 +159,12 @@
|
|
|
159
159
|
// Point `--mw-section-padding-block` at it to switch a page over - a choice
|
|
160
160
|
// like the presets are, not the default.
|
|
161
161
|
--mw-section-padding-fluid: #{fluid(spacing('7'), spacing('12'), $to: 'xl')};
|
|
162
|
-
|
|
162
|
+
// The section head: the gap it leaves to the content below, the space
|
|
163
|
+
// between its rule and the title, and the mark sitting on that rule.
|
|
164
|
+
--mw-section-head-gap: #{spacing('10')};
|
|
165
|
+
--mw-section-head-pad: #{spacing('6')};
|
|
166
|
+
--mw-section-head-mark-width: 80px;
|
|
167
|
+
--mw-section-head-mark-color: var(--mw-primary-color);
|
|
163
168
|
--mw-scroll-hint-offset: #{spacing('9')};
|
|
164
169
|
--mw-scroll-hint-inline: var(--mw-container-gutter);
|
|
165
170
|
--mw-scroll-hint-reserve: #{spacing('10')};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
@use '../abstracts' as *;
|
|
2
|
+
|
|
3
|
+
@layer mw.components {
|
|
4
|
+
// The block that says how to reach someone - postal address, phone, mail.
|
|
5
|
+
// Belongs on an <address>, which is what the one font-style is for: the
|
|
6
|
+
// element is italic by default, and nobody sets an address in italics.
|
|
7
|
+
.mw-contact {
|
|
8
|
+
font-style: normal;
|
|
9
|
+
display: grid;
|
|
10
|
+
gap: spacing('3');
|
|
11
|
+
|
|
12
|
+
> * {
|
|
13
|
+
margin: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&-row {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-wrap: wrap;
|
|
19
|
+
gap: spacing('1') spacing('4');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Sized rather than auto, so the values line up under each other however
|
|
23
|
+
// long the words in front of them are
|
|
24
|
+
&-label {
|
|
25
|
+
flex: 0 0 5rem;
|
|
26
|
+
color: var(--mw-text-muted-color);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
@use '../abstracts' as *;
|
|
2
|
+
|
|
3
|
+
@layer mw.components {
|
|
4
|
+
// Every fluid value here runs the same ramp: from the width the two-column
|
|
5
|
+
// layout starts at to the width a day card stops growing at. Against the
|
|
6
|
+
// container, not the viewport - the layout switch below is a container query,
|
|
7
|
+
// and sizing off vw would hand a narrow card in a wide window the
|
|
8
|
+
// measurements of a wide one.
|
|
9
|
+
@function _stamp-ramp($min, $max) {
|
|
10
|
+
@return fluid-container($min, $max, $mw-card-wide, 900px);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Named because the today fill cancels the paddings to reach the card border,
|
|
14
|
+
// and the price variant repeats the track list - two copies would drift apart.
|
|
15
|
+
$_mw-date-stamp-pad-top: _stamp-ramp(spacing('4'), spacing('6'));
|
|
16
|
+
$_mw-date-stamp-pad-bottom: _stamp-ramp(spacing('3'), spacing('5'));
|
|
17
|
+
$_mw-date-stamp-day-col: _stamp-ramp(4.25rem, 7rem);
|
|
18
|
+
$_mw-date-stamp-gap: _stamp-ramp(spacing('4'), spacing('7'));
|
|
19
|
+
$_mw-date-stamp-day-size: _stamp-ramp('xl', '3xl');
|
|
20
|
+
|
|
21
|
+
// The date on a dated card - an event, a changelog entry, a day on a menu.
|
|
22
|
+
// Narrow, it is a line above the title. Wide, it turns into a column beside
|
|
23
|
+
// the content, which is the only thing that fills the right half of a card
|
|
24
|
+
// that has a whole row to itself.
|
|
25
|
+
.mw-date-stamp {
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: baseline;
|
|
28
|
+
gap: spacing('3');
|
|
29
|
+
margin-bottom: spacing('4');
|
|
30
|
+
color: var(--mw-text-muted-color);
|
|
31
|
+
|
|
32
|
+
&-day {
|
|
33
|
+
font-size: font-size('sm');
|
|
34
|
+
font-weight: font-weight('bold');
|
|
35
|
+
text-transform: uppercase;
|
|
36
|
+
letter-spacing: 0.08em;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&-date {
|
|
40
|
+
font-size: font-size('sm');
|
|
41
|
+
font-variant-numeric: tabular-nums;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// A fill, not a text colour: the price on the same card is already primary,
|
|
45
|
+
// and two blues compete where one would point. The padding is pulled back
|
|
46
|
+
// out again so the fill bleeds around the line instead of indenting it.
|
|
47
|
+
&-today {
|
|
48
|
+
padding: spacing('2') spacing('3');
|
|
49
|
+
margin-inline: spacing('-3');
|
|
50
|
+
margin-block-start: spacing('-2');
|
|
51
|
+
border-radius: radius('sm') radius('lg') radius('sm') radius('lg');
|
|
52
|
+
background: var(--mw-primary-color);
|
|
53
|
+
color: var(--mw-primary-accent-text-color);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// No box of its own until there are two columns to be one of, so the card body
|
|
58
|
+
// keeps seeing the title, the text and the price as its own children - which
|
|
59
|
+
// is what mw-offer and mw-card-body's last-child rule both select on
|
|
60
|
+
.mw-date-stamp-body {
|
|
61
|
+
display: contents;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@container mw-card (width >= #{$mw-card-wide}) {
|
|
65
|
+
// The rule sits here and not in _cards.scss because the stamp is the guest -
|
|
66
|
+
// the card body's own single column is right for everything that is not one
|
|
67
|
+
.mw-card-body:has(> .mw-date-stamp) {
|
|
68
|
+
display: grid;
|
|
69
|
+
grid-template-columns: $_mw-date-stamp-day-col minmax(0, 1fr);
|
|
70
|
+
// On the same curve as the column, so the dish keeps the width the day
|
|
71
|
+
// and the price give up rather than losing it again to the gutters
|
|
72
|
+
column-gap: $_mw-date-stamp-gap;
|
|
73
|
+
padding-block: $_mw-date-stamp-pad-top $_mw-date-stamp-pad-bottom;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// A third track, for the one price that covers the whole day - it is what the
|
|
77
|
+
// right half of a wide card is otherwise spent on. Only when there is a
|
|
78
|
+
// price: with a dish per row it travels with its dish, and an empty track
|
|
79
|
+
// would still charge the card a gap.
|
|
80
|
+
.mw-card-body:has(> .mw-date-stamp):has(> .mw-price) {
|
|
81
|
+
grid-template-columns: $_mw-date-stamp-day-col minmax(0, 1fr) auto;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// The row is left to stretch to the body, so a today fill can span the whole
|
|
85
|
+
// card - which means each column has to centre its own content instead
|
|
86
|
+
.mw-date-stamp-body {
|
|
87
|
+
display: flex;
|
|
88
|
+
flex-direction: column;
|
|
89
|
+
justify-content: center;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// The card body zeroes its own last child, but the wrapper hides ours from
|
|
93
|
+
// that rule - without this a trailing tag row adds a paragraph margin
|
|
94
|
+
.mw-date-stamp-body > *:last-child {
|
|
95
|
+
margin-bottom: spacing('0');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Beside the dish it prices, not under the description that follows it. The
|
|
99
|
+
// second selector only exists to outrank mw-offer, which pushes a price to
|
|
100
|
+
// the bottom of the card and ties with the first on specificity alone.
|
|
101
|
+
.mw-card-body:has(> .mw-date-stamp) > .mw-price,
|
|
102
|
+
.mw-offer > .mw-card-body:has(> .mw-date-stamp) > .mw-price {
|
|
103
|
+
align-self: center;
|
|
104
|
+
justify-self: end;
|
|
105
|
+
margin-top: spacing('0');
|
|
106
|
+
padding-top: spacing('0');
|
|
107
|
+
text-align: right;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.mw-date-stamp {
|
|
111
|
+
flex-direction: column;
|
|
112
|
+
align-items: flex-start;
|
|
113
|
+
// Stretched to the row, so the day and the date centre against the title
|
|
114
|
+
// and description beside them rather than hanging off the first line
|
|
115
|
+
justify-content: center;
|
|
116
|
+
gap: spacing('2');
|
|
117
|
+
margin-bottom: spacing('0');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Top edge of the card to its bottom one: the body's padding is handed back
|
|
121
|
+
// so the fill reaches the border. Only the two left corners are rounded, and
|
|
122
|
+
// to the card's own arc less the 1px it sits inside - the right edge is an
|
|
123
|
+
// inside edge and a cut is what reads as one.
|
|
124
|
+
.mw-date-stamp-today {
|
|
125
|
+
margin-block: calc(-1 * #{$_mw-date-stamp-pad-top})
|
|
126
|
+
calc(-1 * #{$_mw-date-stamp-pad-bottom});
|
|
127
|
+
margin-inline: calc(-1 * #{spacing('5')}) 0;
|
|
128
|
+
padding-block: $_mw-date-stamp-pad-top $_mw-date-stamp-pad-bottom;
|
|
129
|
+
padding-inline: spacing('5');
|
|
130
|
+
border-radius: calc(#{radius-sharp()} - 1px) 0 0
|
|
131
|
+
calc(#{radius('xl')} - 1px);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.mw-date-stamp-day {
|
|
135
|
+
// Tracks the column it sits in, or it would outgrow it on the way down
|
|
136
|
+
font-size: $_mw-date-stamp-day-size;
|
|
137
|
+
line-height: 1;
|
|
138
|
+
letter-spacing: 0.02em;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
@forward 'cards';
|
|
12
12
|
@forward 'code';
|
|
13
13
|
@forward 'coming-soon';
|
|
14
|
+
@forward 'contact';
|
|
14
15
|
@forward 'content-slider';
|
|
16
|
+
@forward 'date-stamp';
|
|
15
17
|
@forward 'divider';
|
|
16
18
|
@forward 'dropdown';
|
|
17
19
|
@forward 'empty-state';
|
|
@@ -21,6 +23,7 @@
|
|
|
21
23
|
@forward 'kanban';
|
|
22
24
|
@forward 'kbd';
|
|
23
25
|
@forward 'lang-switch';
|
|
26
|
+
@forward 'leader-row';
|
|
24
27
|
@forward 'links';
|
|
25
28
|
@forward 'lists';
|
|
26
29
|
@forward 'localhost-indicator';
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
@use '../abstracts' as *;
|
|
2
|
+
|
|
3
|
+
@layer mw.components {
|
|
4
|
+
// Dots on the baseline, not under the descenders; em so they follow font-size
|
|
5
|
+
$_mw-leader-baseline-lift: 0.34em;
|
|
6
|
+
|
|
7
|
+
// A label on the left, its value on the right, a dotted line bridging the
|
|
8
|
+
// gap. The line is the whole point: over a wide row the eye loses track of
|
|
9
|
+
// which value belongs to which label, which is why every printed menu, index
|
|
10
|
+
// and invoice draws one.
|
|
11
|
+
//
|
|
12
|
+
// The leader is the row's own ::before rather than an element in the markup.
|
|
13
|
+
// A generated box on a flex container is a flex item, so "order" can place it
|
|
14
|
+
// between the two spans - and generated content stays out of the
|
|
15
|
+
// accessibility tree, where a filler element would need aria-hidden.
|
|
16
|
+
.mw-leader-row {
|
|
17
|
+
--mw-leader-row-style: dotted;
|
|
18
|
+
--mw-leader-row-width: 2px;
|
|
19
|
+
--mw-leader-row-color: var(--mw-border);
|
|
20
|
+
|
|
21
|
+
display: flex;
|
|
22
|
+
// The values never shrink, so without a wrap the label is the only thing
|
|
23
|
+
// left to give - and it gives until it is one letter per line
|
|
24
|
+
flex-wrap: wrap;
|
|
25
|
+
align-items: flex-end;
|
|
26
|
+
gap: spacing('3');
|
|
27
|
+
margin: 0;
|
|
28
|
+
|
|
29
|
+
&::before {
|
|
30
|
+
content: '';
|
|
31
|
+
order: 1;
|
|
32
|
+
flex: 1 1 auto;
|
|
33
|
+
// Keeps a stub of line visible when label and value nearly fill the row
|
|
34
|
+
min-width: spacing('6');
|
|
35
|
+
border-bottom: var(--mw-leader-row-width) var(--mw-leader-row-style)
|
|
36
|
+
var(--mw-leader-row-color);
|
|
37
|
+
margin-bottom: $_mw-leader-baseline-lift;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&-label {
|
|
41
|
+
order: 0;
|
|
42
|
+
// No min-width override: the default floor is the longest word, so the
|
|
43
|
+
// label wraps between words and stops there instead of going to nothing.
|
|
44
|
+
// Past that floor the row wraps rather than the label shrinking further.
|
|
45
|
+
//
|
|
46
|
+
// The row also works as a dl group, and a dd carries 40px of browser margin
|
|
47
|
+
margin: 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&-value {
|
|
51
|
+
order: 2;
|
|
52
|
+
flex-shrink: 0;
|
|
53
|
+
margin: 0;
|
|
54
|
+
// A price or a page number must not break, and a column of them only
|
|
55
|
+
// lines up with tabular figures.
|
|
56
|
+
white-space: nowrap;
|
|
57
|
+
font-variant-numeric: tabular-nums;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Two values in one row read as a single long range with only a gap between
|
|
61
|
+
// them. The mark takes the leader's colour, so retuning a row moves both.
|
|
62
|
+
// It hangs off the first of the pair, not the second: once the row wraps, a
|
|
63
|
+
// trailing mark reads as "continues below" and a leading one as a slip.
|
|
64
|
+
&-value:has(+ &-value)::after {
|
|
65
|
+
content: '|';
|
|
66
|
+
margin-left: spacing('3');
|
|
67
|
+
color: var(--mw-leader-row-color);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
&-dashed {
|
|
71
|
+
--mw-leader-row-style: dashed;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
&-solid {
|
|
75
|
+
--mw-leader-row-style: solid;
|
|
76
|
+
--mw-leader-row-width: 1px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
&-top {
|
|
80
|
+
align-items: flex-start;
|
|
81
|
+
|
|
82
|
+
&::before {
|
|
83
|
+
// flex-start pins the leader to the top edge, so it drops to the first
|
|
84
|
+
// line's baseline itself instead of being lifted off the last one
|
|
85
|
+
margin: calc(1lh - #{$_mw-leader-baseline-lift}) 0 0;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -159,6 +159,12 @@ $_column-steps-lg: (
|
|
|
159
159
|
grid-template-columns: repeat(auto-fill, minmax(min(350px, 100%), 1fr));
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
// Every row as tall as the tallest rather than as tall as its own contents.
|
|
163
|
+
// A modifier, not a grid of its own - it needs one of the above to size.
|
|
164
|
+
.mw-grid-even {
|
|
165
|
+
grid-auto-rows: 1fr;
|
|
166
|
+
}
|
|
167
|
+
|
|
162
168
|
.mw-grid-lg {
|
|
163
169
|
@extend %grid-base-lg;
|
|
164
170
|
}
|
|
@@ -8,6 +8,25 @@
|
|
|
8
8
|
min-height: 100dvh;
|
|
9
9
|
display: flex;
|
|
10
10
|
flex-direction: column;
|
|
11
|
+
// Numbered section heads count per page body, so a second main on the same
|
|
12
|
+
// document starts at 01 again instead of continuing the first one.
|
|
13
|
+
counter-reset: mw-section-head;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Set in from the container it sits in, and giving that back a step at a time
|
|
17
|
+
// as the screen shrinks. For a column of full-width cards, which at 1200px
|
|
18
|
+
// leaves more empty card than content.
|
|
19
|
+
.mw-container-narrow {
|
|
20
|
+
width: 80%;
|
|
21
|
+
margin-inline: auto;
|
|
22
|
+
|
|
23
|
+
@include media-down('lg') {
|
|
24
|
+
width: 90%;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@include media-down('md') {
|
|
28
|
+
width: 100%;
|
|
29
|
+
}
|
|
11
30
|
}
|
|
12
31
|
|
|
13
32
|
.mw-container {
|
|
@@ -1,65 +1,135 @@
|
|
|
1
1
|
@use '../abstracts' as *;
|
|
2
2
|
|
|
3
3
|
@layer mw.layout {
|
|
4
|
-
// The
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
// The head of a section: a rule, a title, and the line that says what the
|
|
5
|
+
// section is. All three left-aligned, and that is the whole point of the
|
|
6
|
+
// component. Centred running text moves its own left edge with every line
|
|
7
|
+
// break, so the eye has to find the start of each line instead of jumping
|
|
8
|
+
// to a fixed position - fine for a heading, tiring from the third line of
|
|
9
|
+
// body copy on. Aligned, title, lead and content below share one edge, and
|
|
10
|
+
// that edge is what holds a section together.
|
|
11
|
+
.mw-section-head {
|
|
12
|
+
position: relative;
|
|
13
|
+
margin-bottom: var(--mw-section-head-gap);
|
|
14
|
+
padding-top: var(--mw-section-head-pad);
|
|
15
|
+
// Two pixels and not one: the diagonal pattern of mw-section-alternate
|
|
16
|
+
// swallows a hairline, and the rule is the thing that has to survive on
|
|
17
|
+
// every background the framework paints.
|
|
18
|
+
border-top: 2px solid var(--mw-border);
|
|
19
|
+
|
|
20
|
+
// The rule stays quiet so it reads as a boundary and not as a border, and
|
|
21
|
+
// quiet is still hard to see on a patterned band. Hence the mark:
|
|
22
|
+
// a short, thicker piece of the accent colour sitting on the line at the
|
|
23
|
+
// edge everything else starts from. It carries the weight the full-width
|
|
24
|
+
// rule deliberately does not have.
|
|
25
|
+
&::before {
|
|
14
26
|
content: '';
|
|
15
27
|
position: absolute;
|
|
16
|
-
|
|
17
|
-
left:
|
|
18
|
-
transform:
|
|
19
|
-
width:
|
|
20
|
-
height:
|
|
28
|
+
top: 0;
|
|
29
|
+
left: 0;
|
|
30
|
+
transform: translateY(-50%);
|
|
31
|
+
width: var(--mw-section-head-mark-width);
|
|
32
|
+
height: 4px;
|
|
21
33
|
border-radius: radius('xs');
|
|
22
|
-
background:
|
|
34
|
+
background: var(--mw-section-head-mark-color);
|
|
23
35
|
}
|
|
24
36
|
}
|
|
25
37
|
|
|
26
|
-
.mw-section-title {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@include _section-rule(56px, 3px, spacing('-3'));
|
|
38
|
+
.mw-section-head-title {
|
|
39
|
+
margin: spacing('0');
|
|
40
|
+
font-size: fluid('2xl', '4xl', $to: 'lg');
|
|
41
|
+
line-height: 1;
|
|
42
|
+
letter-spacing: -0.02em;
|
|
43
|
+
text-wrap: balance;
|
|
33
44
|
}
|
|
34
45
|
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
margin: spacing('-3') auto spacing('9');
|
|
46
|
+
// Two limits, and the narrower one wins: 65 characters is where a line stops
|
|
47
|
+
// being comfortable, four fifths is what keeps the paragraph from filling the
|
|
48
|
+
// container edge to edge on a wide screen. Below md only the character count
|
|
49
|
+
// is left - four fifths of a phone is a column nothing fits in.
|
|
50
|
+
.mw-section-head-intro {
|
|
51
|
+
max-width: 75ch;
|
|
52
|
+
margin: spacing('4') spacing('0') spacing('0');
|
|
43
53
|
font-size: font-size('md');
|
|
54
|
+
line-height: 1.6;
|
|
44
55
|
color: var(--mw-text-muted-color);
|
|
45
|
-
text-
|
|
46
|
-
|
|
56
|
+
text-wrap: pretty;
|
|
57
|
+
|
|
58
|
+
@include media-up('md') {
|
|
59
|
+
max-width: min(80%, 70ch);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
p {
|
|
63
|
+
margin: spacing('0');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
p + p {
|
|
67
|
+
margin-top: spacing('4');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Opt-in, because a single section on a legal page numbered "01" is noise.
|
|
72
|
+
// The browser counts, so no page keeps its own running order in the markup -
|
|
73
|
+
// and the number sits at the far end of the rule rather than above the title:
|
|
74
|
+
// the mark opens the line, the number closes it, and the title keeps the
|
|
75
|
+
// first thing read on the left.
|
|
76
|
+
.mw-section-head-numbered {
|
|
77
|
+
counter-increment: mw-section-head;
|
|
78
|
+
|
|
79
|
+
&::after {
|
|
80
|
+
content: counter(mw-section-head, decimal-leading-zero);
|
|
81
|
+
position: absolute;
|
|
82
|
+
top: var(--mw-section-head-pad);
|
|
83
|
+
right: 7px;
|
|
84
|
+
color: var(--mw-text-muted-color);
|
|
85
|
+
font-size: font-size('sm');
|
|
86
|
+
font-weight: font-weight('medium');
|
|
87
|
+
line-height: 1;
|
|
88
|
+
// The tracking sits after the last digit too, so it has to come back off
|
|
89
|
+
// the right or the number stands a space short of the edge it aligns to.
|
|
90
|
+
letter-spacing: 0.2em;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// The number owns the right end of the first line - a long title runs into
|
|
94
|
+
// it otherwise, and on a phone that is one word, not a rare case.
|
|
95
|
+
.mw-section-head-title {
|
|
96
|
+
padding-right: spacing('10');
|
|
97
|
+
}
|
|
47
98
|
}
|
|
48
99
|
|
|
100
|
+
// The mark is the one coloured thing in the head, so it is where a section
|
|
101
|
+
// picks up a tone - a danger notice, a success story, a section that belongs
|
|
102
|
+
// to a product colour.
|
|
103
|
+
$_mw-section-head-colors: (secondary, success, warning, danger, info);
|
|
104
|
+
|
|
105
|
+
@each $name in $_mw-section-head-colors {
|
|
106
|
+
.mw-section-head-#{$name} {
|
|
107
|
+
--mw-section-head-mark-color: var(--mw-#{$name}-color);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// The level below the head: the boundary inside a section, not around it.
|
|
112
|
+
// Same left edge, and the rule shrinks to a mark of its own so the two
|
|
113
|
+
// levels read as a hierarchy rather than as two of the same thing.
|
|
49
114
|
.mw-section-subtitle {
|
|
50
115
|
font-size: fluid('xl', '2xl', $to: 'sm');
|
|
51
|
-
//
|
|
52
|
-
// between two components
|
|
53
|
-
|
|
54
|
-
|
|
116
|
+
// One step above the demo gap of spacing('6'), and that step is the whole
|
|
117
|
+
// margin the boundary between two components has over the one between two
|
|
118
|
+
// demos - the heading leans toward what it names, not toward what came
|
|
119
|
+
// before it.
|
|
120
|
+
margin: spacing('8') spacing('0') spacing('4') spacing('0');
|
|
55
121
|
position: relative;
|
|
56
122
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
spacing('-2')
|
|
61
|
-
|
|
62
|
-
|
|
123
|
+
&::after {
|
|
124
|
+
content: '';
|
|
125
|
+
position: absolute;
|
|
126
|
+
bottom: spacing('-2');
|
|
127
|
+
left: 0;
|
|
128
|
+
width: 32px;
|
|
129
|
+
height: 2px;
|
|
130
|
+
border-radius: radius('xs');
|
|
131
|
+
background: var(--mw-secondary-text-color);
|
|
132
|
+
}
|
|
63
133
|
}
|
|
64
134
|
|
|
65
135
|
// Sticky, because the strip is the only way back: inside a long section the
|
|
@@ -135,7 +205,7 @@
|
|
|
135
205
|
// The section boundary steps down to 56px on a phone, so the component
|
|
136
206
|
// boundary steps with it or the two stop being distinguishable
|
|
137
207
|
.mw-section-subtitle {
|
|
138
|
-
margin-top: spacing('
|
|
208
|
+
margin-top: spacing('6');
|
|
139
209
|
}
|
|
140
210
|
}
|
|
141
211
|
|