maverick-wave 4.9.0 → 4.9.1

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/
@@ -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,6 +182,8 @@ 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'),
165
188
  $font-family-base: (
166
189
  'Inter',
package/CHANGELOG.md CHANGED
@@ -6,6 +6,20 @@ 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
+
15
+ ### Changed
16
+
17
+ - header colours derive from `--mw-primary-color` instead of the dark theme background
18
+
19
+ ### Fixed
20
+
21
+ - active navbar link was barely readable on the header
22
+
9
23
  ## [4.9.0] - 2026-08-22
10
24
 
11
25
  ### 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
@@ -1,4 +1,4 @@
1
- @charset "UTF-8";*,:after,:before{margin:0;padding:0;box-sizing:border-box}html{scroll-behavior:smooth;min-width:320px;scroll-padding-top:calc(var(--mw-header-height) + .75rem);-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}body{background:var(--mw-page-background)}body:has(.mw-modal-open){overflow:hidden;height:100vh}a{text-decoration:none;color:var(--mw-text-muted-color);transition:var(--mw-transition)}ul{list-style:none}hr{margin:.5rem 0;color:var(--mw-text-muted-color)}img{max-width:100%;height:auto;display:block}button{background:none;border:none;cursor:pointer}button,input,textarea{font-family:inherit}table{border-collapse:collapse;width:100%}td,th{border:1px solid var(--mw-border);padding:.2rem .35rem;text-align:left}th{background:var(--mw-primary-color);color:var(--mw-primary-accent-text-color)}tbody tr:nth-child(2n){background:var(--mw-gray-background)}:root{--mw-primary-color:#1031bb;--mw-primary-color-hover:color-mix(in hsl, var(--mw-primary-color), #000 15%);--mw-primary-background:color-mix(in srgb, var(--mw-primary-color) 30%, transparent);--mw-primary-background-hover:color-mix(in srgb, var(--mw-primary-color) 50%, transparent);--mw-primary-info-background:var(--mw-primary-background);--mw-secondary-color:#bb5710;--mw-secondary-color-hover:color-mix(in hsl, var(--mw-secondary-color), #000 15%);--mw-secondary-background:color-mix(in srgb, var(--mw-secondary-color) 30%, transparent);--mw-secondary-background-hover:color-mix(in srgb, var(--mw-secondary-color) 50%, transparent);--mw-secondary-info-background:var(--mw-secondary-background);--mw-accent-text-color:#f2f6fc;--mw-primary-accent-text-color:var(--mw-accent-text-color);--mw-secondary-accent-text-color:var(--mw-accent-text-color);--mw-gray-color:#6e6e78;--mw-gray-background:color-mix(in srgb, var(--mw-gray-color) 20%, transparent);--mw-surface-muted:var(--mw-gray-background);--mw-overlay-background:color-mix(in srgb, var(--mw-gray-color) 60%, transparent);--mw-section-alternate-pattern:color-mix(in srgb, var(--mw-gray-color) 30%, transparent);--mw-form-elements-background:#f4f7fb;--mw-form-elements-color:color-mix(in hsl, var(--mw-light-text-color), #000 18%);--mw-success-color:#157f1a;--mw-success-color-hover:color-mix(in hsl, var(--mw-success-color), #000 15%);--mw-success-info-background:color-mix(in srgb, var(--mw-success-color) 30%, transparent);--mw-success-info-background-hover:color-mix(in srgb, var(--mw-success-color) 50%, transparent);--mw-success-accent-text-color:var(--mw-accent-text-color);--mw-warning-color:#d1bb21;--mw-warning-color-hover:color-mix(in hsl, var(--mw-warning-color), #000 15%);--mw-warning-info-background:color-mix(in srgb, var(--mw-warning-color) 30%, transparent);--mw-warning-info-background-hover:color-mix(in srgb, var(--mw-warning-color) 50%, transparent);--mw-warning-accent-text-color:var(--mw-accent-text-color);--mw-danger-color:#d41708;--mw-danger-color-hover:color-mix(in hsl, var(--mw-danger-color), #000 15%);--mw-danger-info-background:color-mix(in srgb, var(--mw-danger-color) 30%, transparent);--mw-danger-info-background-hover:color-mix(in srgb, var(--mw-danger-color) 50%, transparent);--mw-danger-accent-text-color:var(--mw-accent-text-color);--mw-info-color:#0780ca;--mw-info-color-hover:color-mix(in hsl, var(--mw-info-color), #000 15%);--mw-info-info-background:color-mix(in srgb, var(--mw-info-color) 30%, transparent);--mw-info-info-background-hover:color-mix(in srgb, var(--mw-info-color) 50%, transparent);--mw-info-accent-text-color:var(--mw-accent-text-color);--mw-header-background:var(--mw-dark-footer-background);--mw-header-text-color:var(--mw-dark-text-color);--mw-header-navbar-list-color:var(--mw-dark-text-muted-color);--mw-header-navbar-list-active-color:var(--mw-dark-primary-text-color);--mw-header-burgerbutton-color:var(--mw-primary-accent-text-color);--mw-header-burgerbutton-open-color:var(--mw-secondary-accent-text-color);--mw-header-border:var(--mw-dark-border-accent);--mw-dark-page-background:#171f30;--mw-dark-hero-overlay-background:color-mix(in srgb, var(--mw-dark-page-background) 10%, transparent);--mw-dark-card-background:oklch(from var(--mw-dark-page-background) calc(l * 0.85) calc(c * 0.85) h);--mw-dark-footer-background:oklch(from var(--mw-dark-page-background) calc(l * 0.75) calc(c * 0.75) h);--mw-dark-border:oklch(from var(--mw-dark-page-background) calc(l * 1.35) calc(c * 1.35) h);--mw-dark-shadow:color-mix(in srgb, var(--mw-dark-text-color) 30%, transparent);--mw-dark-text-color:#f0eef9;--mw-dark-text-muted-color:color-mix(in oklab, oklch(0.7 0 0), var(--mw-primary-color) 23%);--mw-dark-primary-text-color:oklch(from var(--mw-primary-color) max(l, 0.4) c h);--mw-dark-secondary-text-color:oklch(from var(--mw-secondary-color) max(l, 0.4) c h);--mw-dark-success-text-color:oklch(from var(--mw-success-color) max(l, 0.4) c h);--mw-dark-warning-text-color:oklch(from var(--mw-warning-color) max(l, 0.4) c h);--mw-dark-danger-text-color:oklch(from var(--mw-danger-color) max(l, 0.4) c h);--mw-dark-info-text-color:oklch(from var(--mw-info-color) max(l, 0.4) c h);--mw-dark-border-accent:color-mix(in srgb, var(--mw-dark-primary-text-color) 70%, transparent);--mw-light-page-background:#e7e7f0;--mw-light-hero-overlay-background:color-mix(in srgb, var(--mw-light-page-background) 10%, transparent);--mw-light-card-background:oklch(from var(--mw-light-page-background) calc(l * 1.05) calc(c * 1.05) h);--mw-light-footer-background:oklch(from var(--mw-light-page-background) calc(l * 0.95) calc(c * 0.95) h);--mw-light-border:oklch(from var(--mw-light-page-background) calc(l * 0.8) calc(c * 0.8) h);--mw-light-shadow:color-mix(in srgb, var(--mw-light-text-color) 30%, transparent);--mw-light-text-color:#131925;--mw-light-text-muted-color:color-mix(in oklab, oklch(0.5 0 0), var(--mw-primary-color) 23%);--mw-light-primary-text-color:oklch(from var(--mw-primary-color) min(l, 0.7) c h);--mw-light-secondary-text-color:oklch(from var(--mw-secondary-color) min(l, 0.7) c h);--mw-light-success-text-color:oklch(from var(--mw-success-color) min(l, 0.7) c h);--mw-light-warning-text-color:oklch(from var(--mw-warning-color) min(l, 0.7) c h);--mw-light-danger-text-color:oklch(from var(--mw-danger-color) min(l, 0.7) c h);--mw-light-info-text-color:oklch(from var(--mw-info-color) min(l, 0.7) c h);--mw-light-border-accent:color-mix(in srgb, var(--mw-light-primary-text-color) 70%, transparent);--mw-transition:all 0.3s ease;--mw-internal-theme-mode:switchable;--mw-hero-background:url(https://images.unsplash.com/photo-1591638462868-19cfad9c49d1?q=80&w=1300&auto=format&fit=crop);--mw-header-height:62px;--mw-container-gutter:max(
1
+ @charset "UTF-8";*,:after,:before{margin:0;padding:0;box-sizing:border-box}html{scroll-behavior:smooth;min-width:320px;scroll-padding-top:calc(var(--mw-header-height) + .75rem);-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}body{background:var(--mw-page-background)}body:has(.mw-modal-open){overflow:hidden;height:100vh}a{text-decoration:none;color:var(--mw-text-muted-color);transition:var(--mw-transition)}ul{list-style:none}hr{margin:.5rem 0;color:var(--mw-text-muted-color)}img{max-width:100%;height:auto;display:block}button{background:none;border:none;cursor:pointer}button,input,textarea{font-family:inherit}table{border-collapse:collapse;width:100%}td,th{border:1px solid var(--mw-border);padding:.2rem .35rem;text-align:left}th{background:var(--mw-primary-color);color:var(--mw-primary-accent-text-color)}tbody tr:nth-child(2n){background:var(--mw-gray-background)}:root{--mw-primary-color:#1031bb;--mw-primary-color-hover:color-mix(in hsl, var(--mw-primary-color), #000 15%);--mw-primary-background:color-mix(in srgb, var(--mw-primary-color) 30%, transparent);--mw-primary-background-hover:color-mix(in srgb, var(--mw-primary-color) 50%, transparent);--mw-primary-info-background:var(--mw-primary-background);--mw-secondary-color:#bb5710;--mw-secondary-color-hover:color-mix(in hsl, var(--mw-secondary-color), #000 15%);--mw-secondary-background:color-mix(in srgb, var(--mw-secondary-color) 30%, transparent);--mw-secondary-background-hover:color-mix(in srgb, var(--mw-secondary-color) 50%, transparent);--mw-secondary-info-background:var(--mw-secondary-background);--mw-accent-text-color:#f2f6fc;--mw-primary-accent-text-color:var(--mw-accent-text-color);--mw-secondary-accent-text-color:var(--mw-accent-text-color);--mw-gray-color:#6e6e78;--mw-gray-background:color-mix(in srgb, var(--mw-gray-color) 20%, transparent);--mw-surface-muted:var(--mw-gray-background);--mw-overlay-background:color-mix(in srgb, var(--mw-gray-color) 60%, transparent);--mw-section-alternate-pattern:color-mix(in srgb, var(--mw-gray-color) 30%, transparent);--mw-form-elements-background:#f4f7fb;--mw-form-elements-color:color-mix(in hsl, var(--mw-light-text-color), #000 18%);--mw-success-color:#157f1a;--mw-success-color-hover:color-mix(in hsl, var(--mw-success-color), #000 15%);--mw-success-info-background:color-mix(in srgb, var(--mw-success-color) 30%, transparent);--mw-success-info-background-hover:color-mix(in srgb, var(--mw-success-color) 50%, transparent);--mw-success-accent-text-color:var(--mw-accent-text-color);--mw-warning-color:#d1bb21;--mw-warning-color-hover:color-mix(in hsl, var(--mw-warning-color), #000 15%);--mw-warning-info-background:color-mix(in srgb, var(--mw-warning-color) 30%, transparent);--mw-warning-info-background-hover:color-mix(in srgb, var(--mw-warning-color) 50%, transparent);--mw-warning-accent-text-color:var(--mw-accent-text-color);--mw-danger-color:#d41708;--mw-danger-color-hover:color-mix(in hsl, var(--mw-danger-color), #000 15%);--mw-danger-info-background:color-mix(in srgb, var(--mw-danger-color) 30%, transparent);--mw-danger-info-background-hover:color-mix(in srgb, var(--mw-danger-color) 50%, transparent);--mw-danger-accent-text-color:var(--mw-accent-text-color);--mw-info-color:#0780ca;--mw-info-color-hover:color-mix(in hsl, var(--mw-info-color), #000 15%);--mw-info-info-background:color-mix(in srgb, var(--mw-info-color) 30%, transparent);--mw-info-info-background-hover:color-mix(in srgb, var(--mw-info-color) 50%, transparent);--mw-info-accent-text-color:var(--mw-accent-text-color);--mw-header-background:color-mix(in srgb, var(--mw-primary-color) 16%, #000);--mw-header-text-color:color-mix(in hsl, var(--mw-primary-color), #fff 92%);--mw-header-navbar-list-color:color-mix(in srgb, var(--mw-header-text-color) 70%, transparent);--mw-header-navbar-list-active-color:color-mix(in hsl, var(--mw-primary-color), #fff 35%);--mw-header-burgerbutton-color:var(--mw-primary-accent-text-color);--mw-header-burgerbutton-open-color:var(--mw-secondary-accent-text-color);--mw-header-border:color-mix(in srgb, var(--mw-header-navbar-list-active-color) 40%, transparent);--mw-dark-page-background:#171f30;--mw-dark-hero-overlay-background:color-mix(in srgb, var(--mw-dark-page-background) 10%, transparent);--mw-dark-card-background:oklch(from var(--mw-dark-page-background) calc(l * 0.85) calc(c * 0.85) h);--mw-dark-footer-background:oklch(from var(--mw-dark-page-background) calc(l * 0.75) calc(c * 0.75) h);--mw-dark-border:oklch(from var(--mw-dark-page-background) calc(l * 1.35) calc(c * 1.35) h);--mw-dark-shadow:color-mix(in srgb, var(--mw-dark-text-color) 30%, transparent);--mw-dark-text-color:#f0eef9;--mw-dark-text-muted-color:color-mix(in oklab, oklch(0.7 0 0), var(--mw-primary-color) 23%);--mw-dark-primary-text-color:oklch(from var(--mw-primary-color) max(l, 0.4) c h);--mw-dark-secondary-text-color:oklch(from var(--mw-secondary-color) max(l, 0.4) c h);--mw-dark-success-text-color:oklch(from var(--mw-success-color) max(l, 0.4) c h);--mw-dark-warning-text-color:oklch(from var(--mw-warning-color) max(l, 0.4) c h);--mw-dark-danger-text-color:oklch(from var(--mw-danger-color) max(l, 0.4) c h);--mw-dark-info-text-color:oklch(from var(--mw-info-color) max(l, 0.4) c h);--mw-dark-border-accent:color-mix(in srgb, var(--mw-dark-primary-text-color) 70%, transparent);--mw-light-page-background:#e7e7f0;--mw-light-hero-overlay-background:color-mix(in srgb, var(--mw-light-page-background) 10%, transparent);--mw-light-card-background:oklch(from var(--mw-light-page-background) calc(l * 1.05) calc(c * 1.05) h);--mw-light-footer-background:oklch(from var(--mw-light-page-background) calc(l * 0.95) calc(c * 0.95) h);--mw-light-border:oklch(from var(--mw-light-page-background) calc(l * 0.8) calc(c * 0.8) h);--mw-light-shadow:color-mix(in srgb, var(--mw-light-text-color) 30%, transparent);--mw-light-text-color:#131925;--mw-light-text-muted-color:color-mix(in oklab, oklch(0.5 0 0), var(--mw-primary-color) 23%);--mw-light-primary-text-color:oklch(from var(--mw-primary-color) min(l, 0.7) c h);--mw-light-secondary-text-color:oklch(from var(--mw-secondary-color) min(l, 0.7) c h);--mw-light-success-text-color:oklch(from var(--mw-success-color) min(l, 0.7) c h);--mw-light-warning-text-color:oklch(from var(--mw-warning-color) min(l, 0.7) c h);--mw-light-danger-text-color:oklch(from var(--mw-danger-color) min(l, 0.7) c h);--mw-light-info-text-color:oklch(from var(--mw-info-color) min(l, 0.7) c h);--mw-light-border-accent:color-mix(in srgb, var(--mw-light-primary-text-color) 70%, transparent);--mw-transition:all 0.3s ease;--mw-internal-theme-mode:switchable;--mw-hero-background:url(https://images.unsplash.com/photo-1591638462868-19cfad9c49d1?q=80&w=1300&auto=format&fit=crop);--mw-header-height:62px;--mw-container-gutter:max(
2
2
  clamp(1rem, 4.2vw + 0.5rem, 4rem),
3
3
  env(safe-area-inset-left, 0px),
4
4
  env(safe-area-inset-right, 0px)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maverick-wave",
3
- "version": "4.9.0",
3
+ "version": "4.9.1",
4
4
  "config": {
5
5
  "version_short": "4.9"
6
6
  },
@@ -24,7 +24,7 @@
24
24
  "bugs": {
25
25
  "url": "https://github.com/m1well/maverick-wave/issues"
26
26
  },
27
- "homepage": "https://maverickwave.m1well.com/",
27
+ "homepage": "https://maverick-wave.m1well.com/",
28
28
  "author": "m1well",
29
29
  "license": "MIT",
30
30
  "keywords": [
@@ -73,12 +73,28 @@ $muted-tint: 23% !default;
73
73
  // room for a low card factor.
74
74
  $card-surface-dark: 0.85 !default;
75
75
  $card-surface-light: 1.05 !default;
76
- // Footer and header chrome. In the dark theme they step further out than the
77
- // card, in the light theme they step the other way, so the band under the page
78
- // reads as chrome and not as another card.
76
+ // The footer band. In the dark theme it steps further out than the card, in the
77
+ // light theme it steps the other way, so the band under the page reads as chrome
78
+ // and not as another card. The header is not part of this - see below.
79
79
  $footer-surface-dark: 0.75 !default;
80
80
  $footer-surface-light: 0.95 !default;
81
81
 
82
+ // The header bar. It stays dark in both themes, so it cannot be part of the
83
+ // surface stack above: a project that only ever shows the light theme would be
84
+ // styling its header through a dark page color it never configured, and the bar
85
+ // would keep the framework default no matter what the palette says.
86
+ //
87
+ // It is built from the primary color instead - the one token every palette has
88
+ // to set - darkened straight toward black, which is the ramp every color tool
89
+ // shows as a color's shades. Kept well past the bottom of that ramp on purpose:
90
+ // this deep the brand hue is a tint on near-black rather than a color of its
91
+ // own, which is what keeps the bar reading as chrome behind the page.
92
+ //
93
+ // Lower it for a darker bar. The ink on the bar is near-white, so going far up
94
+ // means overriding --mw-header-text-color and
95
+ // --mw-header-navbar-list-active-color with it.
96
+ $header-surface: 16% !default;
97
+
82
98
  // ---------------------------------------------------------------------------
83
99
  // Derivation helpers
84
100
  //
@@ -123,6 +139,17 @@ $footer-surface-light: 0.95 !default;
123
139
  );
124
140
  }
125
141
 
142
+ // Darkened straight toward black in sRGB - the ramp a color tool prints as a
143
+ // color's shades, where $amount is how much of the color survives. shade()
144
+ // cannot stand in for it: mixing in hsl scales saturation along with lightness
145
+ // and hands back a washed-out tone, which is what a hover state wants and what
146
+ // a surface meant to still read as the brand color does not.
147
+ @function deepen($name, $amount) {
148
+ @return string.unquote(
149
+ 'color-mix(in srgb, var(--mw-#{$name}) #{$amount}, black)'
150
+ );
151
+ }
152
+
126
153
  // The two ink variants. They clamp lightness in OKLch and keep hue and chroma,
127
154
  // which is what makes them palette-agnostic: the same expression lifts a very
128
155
  // dark color, deepens a very light one and leaves everything in between alone.
@@ -300,21 +327,22 @@ $light-theme-colors: (
300
327
  'border-accent': fade('light-primary-text-color', 70%),
301
328
  );
302
329
 
303
- // Header/navbar colors. They stay dark in both themes but can be retuned on
304
- // their own, hence the dark-* references. Emitted as --mw-header-<key>.
330
+ // Header/navbar colors. The bar is dark in both themes, so every tone here is
331
+ // built from the primary color rather than from a theme token: the header is the
332
+ // one piece of chrome a light-only project would otherwise be styling through
333
+ // dark-theme values it never set. Emitted as --mw-header-<key>, and each one is
334
+ // still overridable on its own.
305
335
  $header-colors: (
306
- 'background': token('dark-footer-background'),
307
- 'text-color': token('dark-text-color'),
308
- 'navbar-list-color': token('dark-text-muted-color'),
309
- // Primary carries the navigation, secondary stays a signal. The bar is dark in
310
- // both themes, so the active item takes the dark ink tone in both.
311
- 'navbar-list-active-color': token('dark-primary-text-color'),
336
+ 'background': deepen('primary-color', $header-surface),
337
+ 'text-color': tint('primary-color', 92%),
338
+ 'navbar-list-color': fade('header-text-color', 70%),
339
+ 'navbar-list-active-color': tint('primary-color', 35%),
312
340
  // The burger sits on the primary button surface, and on the secondary one
313
341
  // while the drawer is open, so it takes the label ink of each - not the
314
342
  // header text color, which is picked for the dark bar behind it.
315
343
  'burgerbutton-color': token('primary-accent-text-color'),
316
344
  'burgerbutton-open-color': token('secondary-accent-text-color'),
317
- 'border': token('dark-border-accent'),
345
+ 'border': fade('header-navbar-list-active-color', 40%),
318
346
  );
319
347
  // Drives the bar height, the anchor scroll offset and the mobile drawer padding.
320
348
  // 59px is the intrinsic height: 42px logo + 2 × spacing('3') + 1px border.