maverick-wave 4.9.0 → 4.9.2

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.
@@ -114,7 +114,10 @@ same height as the login and burger buttons.
114
114
  `--mw-header-text-color`, `--mw-header-navbar-list-color`,
115
115
  `--mw-header-navbar-list-active-color`, `--mw-header-burgerbutton-color`,
116
116
  `--mw-header-border`) so the chrome can be retuned without touching the brand
117
- palette.
117
+ palette. All of them derive from `--mw-primary-color`, not from a theme
118
+ colour: the bar is dark in both themes and a light-only project must not have
119
+ to configure dark-theme values to change it. The bar itself is the primary
120
+ darkened toward black, `$header-surface` (16%) - see `theming.md`.
118
121
 
119
122
  **Localhost indicator.** Put `mw-localhost-indicator-activated` on the header
120
123
  and the shipped JS prepends a pulsing bar when the host is localhost/127.0.0.1/
@@ -231,8 +234,23 @@ width.
231
234
  ```
232
235
 
233
236
  A `mw-container` that contains a `mw-hero` switches to full-bleed, full-height
234
- mode with the background image from `--mw-hero-background` and a blurred overlay
235
- (`--mw-hero-overlay-background`). `mw-home-content-fade` fades the content in.
237
+ mode with the background image from `--mw-hero-background`.
238
+ `mw-home-content-fade` fades the content in.
239
+
240
+ The ink on that image comes from `--mw-hero-text-color` and does **not** follow
241
+ the theme, because the photo does not either - a theme-bound colour would go
242
+ dark over an unchanged dark image the moment the light theme is on. It defaults
243
+ to the light end of the palette; for a bright photo set it per page:
244
+
245
+ ```css
246
+ .hero-page {
247
+ --mw-hero-text-color: var(--mw-light-text-color);
248
+ }
249
+ ```
250
+
251
+ Components that paint their own surface (`mw-card`, `mw-panel`, `mw-modal`,
252
+ `mw-tile`, `mw-calendar`) are exempt and keep the theme's ink - a card in the
253
+ hero is still a card.
236
254
 
237
255
  ## Grid
238
256
 
@@ -45,40 +45,40 @@ Safari 16.4+, Firefox 128+.
45
45
 
46
46
  ## Which token for what
47
47
 
48
- | Token | Role |
49
- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
50
- | `--mw-primary-color` | Brand colour as a **fill**: primary buttons, table headers, bars, badges - the label on top is `--mw-primary-accent-text-color` |
51
- | `--mw-primary-text-color` | Brand colour as **ink** on a theme surface: text, icons, focus rings, accent borders. Derived by clamping OKLch lightness (`max(l, .68)` on dark, `min(l, .55)` on light), so a colour already in range is used untouched |
52
- | `--mw-primary-color-hover` | Solid hover surface (derived: base + `$hover-shift` black, in both themes) |
53
- | `--mw-primary-background` | 20% tint - focus halo, alert/badge/tag surface, scrollbar tracks |
54
- | `--mw-primary-background-hover` | 45% tint - row and list hover |
55
- | `--mw-primary-info-background` | Alias of `--mw-primary-background`, so a component can interpolate one name across all six colours |
56
- | `--mw-border-accent` | Translucent accent **line**: panel rules, dividers, tab underlines. Theme-aware (70% of `--mw-*-text-color`) |
57
- | `--mw-secondary-*` | Same set for the second brand colour |
58
- | `--mw-success/warning/danger/info-color` | Status colours, each with `-text-color`, `-color-hover`, `-info-background`, `-info-background-hover` |
59
- | `--mw-accent-text-color` | Text on any solid coloured surface (buttons, table/panel headers, badges, stepper dots) |
60
- | `--mw-primary-accent-text-color` | Per colour override of that label. Same for `secondary`, `success`, `warning`, `danger`, `info`. Defaults to `--mw-accent-text-color`, so set one only when a colour needs the opposite label - a neon primary on a dark palette |
61
- | `--mw-gray-color` | Neutral foreground: muted icons, tooltips |
62
- | `--mw-gray-background` | Subtle neutral surface (20% alpha): zebra rows, disabled fields, tracks, skeletons |
63
- | `--mw-surface-muted` | Alias of `--mw-gray-background` under the name you reach for: a slightly set-off area _inside_ a card - hint block, framed paragraph, form summary |
64
- | `--mw-overlay-background` | Heavy scrim (60%) behind modals and blocking spinners |
65
- | `--mw-page-background`, `--mw-card-background`, `--mw-footer-background`, `--mw-border`, `--mw-shadow`, `--mw-text-color`, `--mw-text-muted-color`, `--mw-hero-overlay-background` | The **active theme** - aliases pointing at the `--mw-dark-*` or `--mw-light-*` set |
66
- | `--mw-header-*` | Header chrome: `background`, `text-color`, `navbar-list-color`, `navbar-list-active-color`, `burgerbutton-color`, `burgerbutton-open-color`, `border` - dark in both themes. The two burger tokens default to the primary and secondary label ink, because the burger sits on those two surfaces |
67
- | `--mw-form-elements-background`, `--mw-form-elements-color` | Form controls stay light in both themes and therefore have their own pair |
68
- | `--mw-font-family-base`, `-heading`, `-mono` | Font stacks - system stacks by default (`-mono` leads with Fira Code); no font is bundled. Configurable in SCSS, see below |
69
- | `--mw-hero-background` | Hero image (`url(...)`) |
70
- | `--mw-transition` | Global transition (`all 0.3s ease`) |
71
- | `--mw-card-img-height` | Per-card image height (default `210px`; `mw-card-lg`/`-xl` set it to 340px/480px, 260px/340px below `sm`) |
72
- | `--mw-card-addon-color` | Background of `mw-card-badge` / `mw-card-ribbon`; the `mw-card-addon-*` classes set it, override it for a custom colour |
73
- | `--mw-card-addon-text-color` | Label on that badge/ribbon; the `mw-card-addon-*` classes point it at the matching `--mw-*-accent-text-color` |
74
- | `--mw-progress-ink` | Label inside `mw-progress-inline-label`; the `mw-progress-*` colour classes point it at the matching `--mw-*-accent-text-color` |
75
- | `--mw-table-scroll-height` | Per-table height cap for `mw-table-responsive-scroll` |
76
- | `--mw-kanban-background`, `--mw-kanban-lane-border`, `--mw-kanban-column-min-height` | Per-board surface, lane border and lane floor (120px, 90px on `mw-kanban-compact`) |
77
- | `--mw-container-gutter`, `--mw-container-width` | Page gutter of `mw-container` (fluid `clamp(1rem, 4.2vw + 0.5rem, 4rem)`, never below the safe-area inset) and the width derived from it (`min(1200px, 100% - 2 * gutter)`) |
78
- | `--mw-section-padding-block` | Top/bottom rhythm of `mw-section` (1.75rem) |
79
- | `--mw-calendar-dot` | Colour of a single calendar dot - set it per dot or per cell; the `mw-calendar-dot-*` classes are presets for it |
80
- | `--mw-scroll-hint-cover` | Colour the scroll hint on a tab bar fades into. Preset to the page, re-pointed to the card background inside `mw-card`, `mw-panel`, `mw-modal`, `mw-tile`, `mw-calendar` |
81
- | `--mw-internal-theme-mode` | Read-only: what `$mw-theme-mode` was compiled to |
48
+ | Token | Role |
49
+ | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
50
+ | `--mw-primary-color` | Brand colour as a **fill**: primary buttons, table headers, bars, badges - the label on top is `--mw-primary-accent-text-color` |
51
+ | `--mw-primary-text-color` | Brand colour as **ink** on a theme surface: text, icons, focus rings, accent borders. Derived by clamping OKLch lightness (`max(l, .68)` on dark, `min(l, .55)` on light), so a colour already in range is used untouched |
52
+ | `--mw-primary-color-hover` | Solid hover surface (derived: base + `$hover-shift` black, in both themes) |
53
+ | `--mw-primary-background` | 20% tint - focus halo, alert/badge/tag surface, scrollbar tracks |
54
+ | `--mw-primary-background-hover` | 45% tint - row and list hover |
55
+ | `--mw-primary-info-background` | Alias of `--mw-primary-background`, so a component can interpolate one name across all six colours |
56
+ | `--mw-border-accent` | Translucent accent **line**: panel rules, dividers, tab underlines. Theme-aware (70% of `--mw-*-text-color`) |
57
+ | `--mw-secondary-*` | Same set for the second brand colour |
58
+ | `--mw-success/warning/danger/info-color` | Status colours, each with `-text-color`, `-color-hover`, `-info-background`, `-info-background-hover` |
59
+ | `--mw-accent-text-color` | Text on any solid coloured surface (buttons, table/panel headers, badges, stepper dots) |
60
+ | `--mw-primary-accent-text-color` | Per colour override of that label. Same for `secondary`, `success`, `warning`, `danger`, `info`. Defaults to `--mw-accent-text-color`, so set one only when a colour needs the opposite label - a neon primary on a dark palette |
61
+ | `--mw-gray-color` | Neutral foreground: muted icons, tooltips |
62
+ | `--mw-gray-background` | Subtle neutral surface (20% alpha): zebra rows, disabled fields, tracks, skeletons |
63
+ | `--mw-surface-muted` | Alias of `--mw-gray-background` under the name you reach for: a slightly set-off area _inside_ a card - hint block, framed paragraph, form summary |
64
+ | `--mw-overlay-background` | Heavy scrim (60%) behind modals and blocking spinners |
65
+ | `--mw-page-background`, `--mw-card-background`, `--mw-footer-background`, `--mw-border`, `--mw-shadow`, `--mw-text-color`, `--mw-text-muted-color` | The **active theme** - aliases pointing at the `--mw-dark-*` or `--mw-light-*` set |
66
+ | `--mw-header-*` | Header chrome: `background`, `text-color`, `navbar-list-color`, `navbar-list-active-color`, `burgerbutton-color`, `burgerbutton-open-color`, `border` - dark in both themes. The two burger tokens default to the primary and secondary label ink, because the burger sits on those two surfaces |
67
+ | `--mw-form-elements-background`, `--mw-form-elements-color` | Form controls stay light in both themes and therefore have their own pair |
68
+ | `--mw-font-family-base`, `-heading`, `-mono` | Font stacks - system stacks by default (`-mono` leads with Fira Code); no font is bundled. Configurable in SCSS, see below |
69
+ | `--mw-hero-background`, `--mw-hero-text-color` | Hero image (`url(...)`) and the ink on it. Fixed across themes - the photo does not change with the theme, so its text must not either. Defaults to the light end of the palette |
70
+ | `--mw-transition` | Global transition (`all 0.3s ease`) |
71
+ | `--mw-card-img-height` | Per-card image height (default `210px`; `mw-card-lg`/`-xl` set it to 340px/480px, 260px/340px below `sm`) |
72
+ | `--mw-card-addon-color` | Background of `mw-card-badge` / `mw-card-ribbon`; the `mw-card-addon-*` classes set it, override it for a custom colour |
73
+ | `--mw-card-addon-text-color` | Label on that badge/ribbon; the `mw-card-addon-*` classes point it at the matching `--mw-*-accent-text-color` |
74
+ | `--mw-progress-ink` | Label inside `mw-progress-inline-label`; the `mw-progress-*` colour classes point it at the matching `--mw-*-accent-text-color` |
75
+ | `--mw-table-scroll-height` | Per-table height cap for `mw-table-responsive-scroll` |
76
+ | `--mw-kanban-background`, `--mw-kanban-lane-border`, `--mw-kanban-column-min-height` | Per-board surface, lane border and lane floor (120px, 90px on `mw-kanban-compact`) |
77
+ | `--mw-container-gutter`, `--mw-container-width` | Page gutter of `mw-container` (fluid `clamp(1rem, 4.2vw + 0.5rem, 4rem)`, never below the safe-area inset) and the width derived from it (`min(1200px, 100% - 2 * gutter)`) |
78
+ | `--mw-section-padding-block` | Top/bottom rhythm of `mw-section` (1.75rem) |
79
+ | `--mw-calendar-dot` | Colour of a single calendar dot - set it per dot or per cell; the `mw-calendar-dot-*` classes are presets for it |
80
+ | `--mw-scroll-hint-cover` | Colour the scroll hint on a tab bar fades into. Preset to the page, re-pointed to the card background inside `mw-card`, `mw-panel`, `mw-modal`, `mw-tile`, `mw-calendar` |
81
+ | `--mw-internal-theme-mode` | Read-only: what `$mw-theme-mode` was compiled to |
82
82
 
83
83
  `--mw-container-gutter`, `--mw-container-width` and `--mw-section-padding-block`
84
84
  are the knobs a good default cannot settle, because the right answer differs per
@@ -119,8 +119,29 @@ Two rules that prevent most colour bugs:
119
119
  panels. Keep the footer further out than the card in the dark theme and on
120
120
  the other side in the light one, or the footer stops reading as chrome. The
121
121
  border factor is not configurable - it runs against the card by design.
122
- - Header, footer chrome and form controls deliberately stay dark/light
123
- respectively in both themes.
122
+ - Footer chrome and form controls deliberately stay dark/light respectively in
123
+ both themes, and so does the header - see the next point for where its colour
124
+ comes from.
125
+ - The header bar is **not** part of that surface stack. It is
126
+ `--mw-primary-color` darkened straight toward black - `$header-surface` (16%)
127
+ is how much of the colour survives, the same shade ramp a colour tool prints.
128
+ It sits well past the bottom of that ramp so the hue reads as a tint on
129
+ near-black, not as a colour of its own. That matters for a light-only project:
130
+ while the bar was derived from the dark page background, its colour was frozen
131
+ at the framework default nobody had configured. Every `--mw-header-*` token
132
+ now follows the primary, and each is still overridable on its own.
133
+ - The ink on the bar is mixed off the same primary: `--mw-header-text-color` is
134
+ `tint(92%)` and `--mw-header-navbar-list-active-color` - the current page and
135
+ the hover tone both - is `tint(35%)`, so the active item reads as the brand
136
+ colour rather than a washed-out pastel. Do not reach for
137
+ `--mw-primary-text-color` here: that bound is calibrated against the page
138
+ background and lets a mid-dark primary through untouched, which on this much
139
+ darker bar lands around 2:1. At the default bar the active tone clears 5:1 on
140
+ every palette; a near-black primary is the one case that falls short (~3.5:1,
141
+ the bar is near-black too) - override the token there.
142
+ - Raising `$header-surface` for a lighter bar eats into that margin, since only
143
+ the bar moves and the ink stays put. Past roughly 30% check the active tone,
144
+ or move it down with the bar.
124
145
  - Persisting the choice, the toggle UI and the initial class are the
125
146
  application's job in a SPA (`examples/angular-services.md`). The shipped JS
126
147
  does it for static pages using `localStorage` under the key `mw-theme`.
@@ -161,7 +182,11 @@ effect, because the root colours are declared with `!default`.
161
182
  $card-surface-light: 1.05,
162
183
  $footer-surface-dark: 0.75,
163
184
  $footer-surface-light: 0.95,
185
+ // the header bar - how much of the primary survives darkening toward black
186
+ $header-surface: 16%,
164
187
  $mw-hero-image: url('/assets/hero.jpg'),
188
+ // ink on that image - fixed, because the image is
189
+ $mw-hero-text-color: var(--mw-dark-text-color),
165
190
  $font-family-base: (
166
191
  'Inter',
167
192
  sans-serif,
package/CHANGELOG.md CHANGED
@@ -6,6 +6,26 @@ Patch releases are only for test purposes - here I only document major and minor
6
6
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
7
7
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
+ ## [4.10.0] - 2026-08-24
10
+
11
+ ### Added
12
+
13
+ - `$header-surface` - SCSS knob for how dark the header bar sits
14
+ - `$mw-hero-text-color` - ink on the hero image, fixed across themes
15
+
16
+ ### Changed
17
+
18
+ - header colours derive from `--mw-primary-color` instead of the dark theme background
19
+
20
+ ### Removed
21
+
22
+ - hero overlay and `--mw-hero-overlay-background`
23
+
24
+ ### Fixed
25
+
26
+ - active navbar link was barely readable on the header
27
+ - hero text went dark over an unchanged image in light mode
28
+
9
29
  ## [4.9.0] - 2026-08-22
10
30
 
11
31
  ### Added
package/README.md CHANGED
@@ -104,10 +104,11 @@ backgrounds, borders, muted text - is derived from them at runtime with
104
104
 
105
105
  Setting `--mw-primary-color` alone also retunes `--mw-primary-color-hover`,
106
106
  `--mw-primary-background`, `--mw-primary-background-hover`,
107
- `--mw-primary-text-color` and `--mw-border-accent`. The same holds for
108
- `--mw-dark-page-background`, which drives the dark card, footer and border
109
- tones. Each derived token can still be overridden individually if you want to
110
- break out of the scale.
107
+ `--mw-primary-text-color`, `--mw-border-accent` and the whole `--mw-header-*`
108
+ set - the bar is the primary darkened toward black, so the chrome follows the
109
+ brand without a second value. The same holds for `--mw-dark-page-background`,
110
+ which drives the dark card, footer and border tones. Each derived token can
111
+ still be overridden individually if you want to break out of the scale.
111
112
 
112
113
  > The derivation needs `color-mix()` **and** relative colour syntax
113
114
  > (`oklch(from ...)`): Chrome 119+, Safari 16.4+, Firefox 128+. Older browsers