Skip to content

Commit 15896e4

Browse files
committed
Add dark theme tokens and dual-image hero
Introduce dark-mode design tokens and swap many color uses to light-dark() with new variables (--color-obsidian, --color-card-dark, --color-muted, --color-rust-bright). Update global styles (styles.css) to map background, text, link, shaded and border tokens for dark theme. Adjust component styles (cards, footer, header, hero, related-articles, tabs, teaser) to use the new dark tokens and heritage border variable so UI elements render correctly in dark mode. Add dual-image hero support: CSS rules to show/hide light vs dark hero images and a mask/opacity for the dark image, plus JS (hero.js) to detect two <picture> elements, tag them as light/dark and eager-load images for LCP. Small footer/header/button tweaks included for consistent dark appearance (border-top, hover colors, button backgrounds and shadows).
1 parent 8f2a4c2 commit 15896e4

File tree

9 files changed

+89
-42
lines changed

9 files changed

+89
-42
lines changed

blocks/cards/cards.css

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
}
1313

1414
.cards > ul > li {
15-
border: 1px solid light-dark(var(--color-gray-200), var(--color-gray-700));
16-
background: light-dark(var(--color-light), var(--color-gray-900));
15+
border: 1px solid light-dark(var(--color-gray-200), rgb(245 242 237 / 10%));
16+
background: light-dark(var(--color-light), var(--color-card-dark));
1717
display: flex;
1818
flex-direction: column;
1919
border-radius: 12px;
@@ -96,7 +96,7 @@
9696
border: var(--border-heritage);
9797
border-radius: var(--border-radius-heritage);
9898
padding: 45px;
99-
background: light-dark(var(--color-parchment), var(--color-gray-900));
99+
background: light-dark(var(--color-parchment), var(--color-card-dark));
100100
transition: all 0.5s cubic-bezier(0.165, 0.84, 0.44, 1);
101101
}
102102

@@ -155,7 +155,7 @@
155155
.cards.bento > ul > li:not(.cards-card-featured) .cards-card-body p:not(.cards-card-tag) {
156156
font-size: 0.95rem;
157157
opacity: 0.8;
158-
color: light-dark(var(--color-ink), var(--color-gray-300));
158+
color: light-dark(var(--color-ink), var(--color-muted));
159159
}
160160

161161
/* Focus */

blocks/footer/footer.css

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
footer {
22
width: 100%;
3-
background-color: var(--color-rust);
4-
color: var(--color-light);
3+
background-color: light-dark(var(--color-rust), #080d0d);
4+
color: var(--color-parchment);
5+
border-top: light-dark(none, var(--border-heritage));
56
font-size: var(--body-font-size-xs);
67
}
78

@@ -94,7 +95,7 @@ footer .footer > div > div:nth-child(4) li {
9495
}
9596

9697
footer .footer a:any-link {
97-
color: var(--color-light);
98+
color: var(--color-parchment);
9899
}
99100

100101
footer .footer > div > div:nth-child(4) a {

blocks/header/header.css

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ header {
2929
--nav-bg: var(--background-color);
3030
--nav-bg-hover: var(--header-hover-bg);
3131
--nav-bg-link-hover: var(--header-link-hover-bg);
32-
--nav-bg-dropdown: var(--background-color);
33-
--nav-bg-dropdown-mobile: light-dark(var(--color-gray-100), var(--color-gray-800));
34-
--nav-bg-mega: var(--color-shaded);
35-
--nav-bg-hover-item: var(--light-color);
32+
--nav-bg-dropdown: light-dark(var(--background-color), var(--color-card-dark));
33+
--nav-bg-dropdown-mobile: light-dark(var(--color-gray-100), var(--color-card-dark));
34+
--nav-bg-mega: light-dark(var(--color-parchment), var(--color-obsidian));
35+
--nav-bg-hover-item: light-dark(var(--light-color), var(--color-card-dark));
3636

3737
/* header uses neutral hover color */
3838
--nav-hover-color: light-dark(var(--color-rust), var(--color-gold));
@@ -50,7 +50,7 @@ header {
5050
}
5151

5252
header .nav-wrapper {
53-
background-color: #faf8f5;
53+
background-color: light-dark(#faf8f5, var(--color-obsidian));
5454
width: 100%;
5555
z-index: 1000;
5656
position: fixed;
@@ -914,7 +914,7 @@ header nav .nav-tools .nav-language-menu a:focus-visible {
914914
top: var(--mega-top, var(--nav-height, 64px));
915915
padding: var(--space-xl) var(--space-xl);
916916
border-bottom: var(--border-heritage);
917-
background-color: #faf8f5;
917+
background-color: light-dark(#faf8f5, var(--color-obsidian));
918918
color: var(--text-color);
919919
box-shadow: var(--header-drop-shadow);
920920
z-index: 999;

blocks/hero/hero.css

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,38 @@
77

88
.hero {
99
position: relative;
10-
background-color: var(--color-parchment);
10+
background-color: light-dark(var(--color-parchment), var(--color-obsidian));
1111
}
1212

1313
/* Image */
14-
.hero > div:first-child {
14+
.hero > div:first-child,
15+
.hero .hero-img-light,
16+
.hero .hero-img-dark {
1517
line-height: 0;
1618
}
1719

20+
/* Dual-image hero: light shown by default, dark hidden */
21+
.hero .hero-img-dark {
22+
display: none;
23+
}
24+
25+
/* Dark theme: swap images (must match light-dark() triggers, not OS preference) */
26+
.dark-scheme .hero .hero-img-light,
27+
:root[data-theme='dark'] .hero .hero-img-light {
28+
display: none;
29+
}
30+
31+
.dark-scheme .hero .hero-img-dark,
32+
:root[data-theme='dark'] .hero .hero-img-dark {
33+
display: block;
34+
}
35+
1836
.hero picture img {
1937
display: block;
38+
width: 100%;
2039
max-height: 520px;
2140
object-fit: cover;
2241
opacity: 0.5;
23-
margin-inline: auto;
2442
}
2543

2644
/* Text overlay */
@@ -59,13 +77,13 @@
5977
font-size: clamp(2rem, 8vw, 4.5rem);
6078
font-weight: 500;
6179
line-height: 1.05;
62-
color: var(--color-ink);
80+
color: light-dark(var(--color-ink), var(--color-parchment));
6381
}
6482

6583
.hero h1 em {
6684
font-weight: 400;
6785
font-style: italic;
68-
color: var(--color-rust);
86+
color: light-dark(var(--color-rust), var(--color-rust-bright));
6987
}
7088

7189
/* Body text — hidden on mobile */
@@ -75,7 +93,7 @@
7593
margin: 0;
7694
font-family: var(--font-family-serif);
7795
font-size: 1.1rem;
78-
color: var(--color-ink);
96+
color: light-dark(var(--color-ink), var(--color-muted));
7997
line-height: 1.7;
8098
}
8199

@@ -96,6 +114,13 @@
96114
object-fit: contain;
97115
}
98116

117+
/* Dark-mode image: blend into obsidian bg with soft edges */
118+
.dark-scheme .hero .hero-img-dark picture img,
119+
:root[data-theme='dark'] .hero .hero-img-dark picture img {
120+
opacity: 0.35;
121+
mask-image: radial-gradient(ellipse 80% 65% at 50% 40%, black 30%, transparent 100%);
122+
}
123+
99124
/* Tablet: show body text */
100125
@media (width >= 600px) {
101126
.hero p:not(.button-container, .hero-tagline) {

blocks/hero/hero.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
/**
22
* Decorates the hero block.
33
* - Sets hero image to eager loading (LCP)
4+
* - Supports dual images: first picture = light mode, second = dark mode
45
* - Identifies the eyebrow/tagline paragraph (first <p> before the <h1>)
56
* and marks it with a class for styling.
67
* @param {Element} block The hero block element
78
*/
89
export default function decorate(block) {
9-
// Hero image is above the fold — load eagerly for LCP
10-
const img = block.querySelector('picture img');
11-
if (img) {
12-
img.loading = 'eager';
10+
const pictures = block.querySelectorAll('picture');
11+
12+
if (pictures.length >= 2) {
13+
// Dual-image hero: first = light, second = dark
14+
const lightDiv = pictures[0].closest('.hero > div');
15+
const darkDiv = pictures[1].closest('.hero > div');
16+
if (lightDiv) lightDiv.classList.add('hero-img-light');
17+
if (darkDiv) darkDiv.classList.add('hero-img-dark');
18+
// Eager-load both for LCP (only the visible one renders)
19+
pictures.forEach((pic) => {
20+
const img = pic.querySelector('img');
21+
if (img) img.loading = 'eager';
22+
});
23+
} else if (pictures.length === 1) {
24+
const img = pictures[0].querySelector('img');
25+
if (img) img.loading = 'eager';
1326
} else {
1427
block.classList.add('no-image');
1528
}

blocks/related-articles/related-articles.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ main .related-articles .related-articles-card {
2222
border: var(--border-heritage);
2323
border-radius: var(--border-radius-heritage);
2424
overflow: clip;
25-
background: light-dark(var(--color-parchment), var(--color-gray-900));
25+
background: light-dark(var(--color-parchment), var(--color-card-dark));
2626
transition: all 0.5s cubic-bezier(0.165, 0.84, 0.44, 1);
2727
}
2828

@@ -78,7 +78,7 @@ main .related-articles .related-articles-card-description {
7878
margin: 0;
7979
font-size: 0.95rem;
8080
line-height: 1.5;
81-
color: light-dark(var(--color-ink), var(--color-gray-300));
81+
color: light-dark(var(--color-ink), var(--color-muted));
8282
opacity: 0.8;
8383
}
8484

blocks/tabs/tabs.css

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ main .section .tabs {
3535
.tabs .tabs-wrapper .section p {
3636
font-family: var(--font-family-serif);
3737
font-size: 1.1rem;
38-
color: var(--color-ink);
38+
color: light-dark(var(--color-ink), var(--color-muted));
3939
opacity: 0.7;
4040
margin-top: 20px;
4141
text-align: center;
@@ -51,15 +51,15 @@ main .section .tabs {
5151
padding: 0 var(--content-padding-inline) var(--space-xs);
5252
overflow-x: auto;
5353
scrollbar-width: thin;
54-
border-bottom: 1px solid rgb(161 79 43 / 15%);
54+
border-bottom: var(--border-heritage);
5555
}
5656

5757
.tabs .tabs-list button {
5858
appearance: none;
5959
background: transparent;
6060
border: 0;
6161
border-bottom: 3px solid transparent;
62-
color: var(--color-ink);
62+
color: light-dark(var(--color-ink), var(--color-muted));
6363
-webkit-text-fill-color: currentcolor;
6464
cursor: pointer;
6565
font-family: var(--body-font-family);
@@ -76,10 +76,10 @@ main .section .tabs {
7676

7777
.tabs .tabs-list button.is-active,
7878
.tabs .tabs-list button[aria-selected='true'] {
79-
color: var(--color-rust);
80-
-webkit-text-fill-color: var(--color-rust);
79+
color: light-dark(var(--color-rust), var(--color-rust-bright));
80+
-webkit-text-fill-color: light-dark(var(--color-rust), var(--color-rust-bright));
8181
opacity: 1;
82-
border-bottom-color: var(--color-rust);
82+
border-bottom-color: light-dark(var(--color-rust), var(--color-rust-bright));
8383
}
8484

8585
.tabs .tabs-list button:hover {
@@ -115,7 +115,7 @@ main .section .tabs {
115115
font-family: var(--font-family-serif);
116116
font-weight: 500;
117117
font-size: var(--heading-font-size-m);
118-
color: var(--color-ink);
118+
color: light-dark(var(--color-ink), var(--color-parchment));
119119
}
120120

121121
.tabs .tab .section > :is(.default-content, .default-content-wrapper, .block-content) {
@@ -143,8 +143,10 @@ main .section .tabs {
143143

144144
.tabs .columns .embed {
145145
max-width: 100%;
146+
border: var(--border-heritage);
146147
border-radius: var(--border-radius-heritage);
147148
overflow: hidden;
149+
background: light-dark(transparent, var(--color-card-dark));
148150
}
149151

150152
/* Columns text — left aligned */

blocks/teaser/teaser.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* Teaser block – Heritage Elite */
22

33
main .teaser {
4-
background: light-dark(var(--color-parchment), var(--color-gray-900));
4+
background: light-dark(var(--color-parchment), var(--color-card-dark));
55
border: var(--border-heritage);
66
border-radius: var(--border-radius-heritage);
77
text-align: center;
@@ -18,7 +18,7 @@ main .teaser > div {
1818
}
1919

2020
main .teaser > div > div a {
21-
color: var(--color-rust);
21+
color: light-dark(var(--color-rust), var(--color-rust-bright));
2222
text-decoration: underline;
2323
text-underline-offset: 0.15em;
2424
text-decoration-color: var(--color-gold);

styles/styles.css

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@
4646
--color-parchment: #f5f2ed;
4747
--color-ink: #1a1a1a;
4848

49+
/* heritage dark palette */
50+
--color-obsidian: #0d1414;
51+
--color-card-dark: #162121;
52+
--color-rust-bright: #d16a3e;
53+
--color-muted: #8b9a9a;
54+
4955
/* color tokens – grays and palette */
5056
--color-gray-100: #f1f1f1;
5157
--color-gray-200: #d3d3d3;
@@ -98,12 +104,12 @@
98104
/* semantic / named colors */
99105
--color-light: rgb(255 255 255);
100106
--color-dark: rgb(0 0 0);
101-
--color-text: light-dark(var(--color-ink), var(--color-light));
102-
--color-link: light-dark(var(--color-ink), var(--color-gray-100));
107+
--color-text: light-dark(var(--color-ink), var(--color-parchment));
108+
--color-link: light-dark(var(--color-ink), var(--color-parchment));
103109
--color-link-hover: light-dark(var(--color-rust), var(--color-gold));
104110
--color-brand: var(--color-rust);
105111
--color-accent: var(--color-gold);
106-
--color-shaded: light-dark(var(--color-parchment), #111);
112+
--color-shaded: light-dark(var(--color-parchment), var(--color-card-dark));
107113

108114
/* fonts */
109115
--font-family: montserrat, "Trebuchet MS", sans-serif;
@@ -136,15 +142,15 @@
136142
--header-height: var(--nav-height);
137143

138144
/* boilerplate compatibility – map to design tokens */
139-
--background-color: light-dark(var(--color-parchment), var(--color-dark));
145+
--background-color: light-dark(var(--color-parchment), var(--color-obsidian));
140146
--light-color: var(--color-shaded);
141147
--dark-color: var(--color-gray-500);
142148
--text-color: var(--color-text);
143149
--link-color: var(--color-link);
144150
--link-hover-color: var(--color-link-hover);
145151

146152
/* heritage border */
147-
--border-heritage: 1px solid rgb(161 79 43 / 15%);
153+
--border-heritage: 1px solid light-dark(rgb(161 79 43 / 15%), rgb(245 242 237 / 10%));
148154
--border-radius-heritage: 24px;
149155
}
150156

@@ -354,7 +360,7 @@ button.button {
354360
gap: var(--space-xs);
355361
max-width: 100%;
356362
margin: 0;
357-
border: 1px solid var(--color-rust);
363+
border: 1px solid light-dark(var(--color-rust), var(--color-rust-bright));
358364
border-radius: 4px;
359365
padding: 20px 50px;
360366
font: inherit;
@@ -365,7 +371,7 @@ button.button {
365371
text-decoration: none;
366372
text-transform: uppercase;
367373
letter-spacing: 2px;
368-
background-color: var(--color-rust);
374+
background-color: light-dark(var(--color-rust), var(--color-rust-bright));
369375
color: var(--color-light);
370376
cursor: pointer;
371377
overflow: hidden;
@@ -396,7 +402,7 @@ button.button:focus-visible {
396402
background-color: var(--color-gold);
397403
border-color: var(--color-gold);
398404
transform: translateY(-2px);
399-
box-shadow: 0 10px 20px rgb(161 79 43 / 20%);
405+
box-shadow: 0 10px 20px light-dark(rgb(161 79 43 / 20%), rgb(209 106 62 / 25%));
400406
cursor: pointer;
401407
text-decoration: none;
402408
}

0 commit comments

Comments
 (0)