diff --git a/CHANGELOG.md b/CHANGELOG.md
index 806c5aaa5..02169fdce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
## Unreleased
### Added
+- **Four demo schools in Zuiddrecht.** `wilgenboom` (Basisschool De Wilgenboom, willow green
+ `#2F6B4A` and sun yellow, Lexend), `vaartveld` (Vaartveld College, cobalt `#1F4FD8` and aqua,
+ Red Hat Display over Red Hat Text), `esdoornveen` (Esdoornveen, mbo college, plum `#5B2E91`
+ and maple rose, IBM Plex Sans with IBM Plex Mono for codes) and `warmtepompacademie`
+ (Warmtepompacademie, petrol `#0B6E7A` and ember, Barlow Semi Condensed over Barlow). Each is
+ built the way `zuiddrecht` is: a light workplace on Nextcloud's radius scale, a generated
+ dark variant, four logos and a login watermark. Every text pair reaches AA in the light and
+ in both dark scopes, computed by `tests/vitest/schoolTokenSets.spec.js`.
+- **Lexend, Red Hat Display, Red Hat Text, Barlow, Barlow Semi Condensed, IBM Plex Sans 500 and
+ IBM Plex Mono 400 and 500** join the bundled typefaces, all SIL OFL 1.1, from Fontsource 5.3.0.
+- **A brand stripe may draw a motif of its own.** A set names any background image in
+ `--nldesign-brand-stripe-image` and the stripe draws it instead of the three bands. The four
+ schools draw their motifs this way: the hanging twigs, the canal, the slanted cut and the
+ temperature line.
+- **Website corners and heading faces on a portal.** A set may name the website's own radii in
+ `--nldesign-website-border-radius` and `--nldesign-website-border-radius-large`; only the
+ public bridge reads them, so the workplace keeps 8px and 12px. The bridge also hands
+ `--nldesign-component-heading-font-family` to the website's headings.
- **Gemeente Zuiddrecht, a demo municipality.** The `zuiddrecht` token set is a light
workplace: blue `#3669A5` for actions, red `#CC0000` as the accent, a white top bar and
navigation, a grey workspace with white cards, Nextcloud's own radius scale and a
diff --git a/README.md b/README.md
index bcb3d6d55..082592c8a 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Apply Dutch government design tokens (NL Design System) to your Nextcloud instan
## Features
-- **59 token sets**: Choose from Dutch government design systems, including:
+- **63 token sets**: Choose from Dutch government design systems, including:
- Rijkshuisstijl (Dutch national government)
- Gemeente Utrecht
- Gemeente Amsterdam
@@ -27,13 +27,13 @@ Apply Dutch government design tokens (NL Design System) to your Nextcloud instan
- **No Build Required**: Tokens are pre-compiled CSS and fonts are bundled and self-hosted (no external CDN)
-- **NL-Government and French-Government Icons**: Includes 1488 SVG icons sourced from `@conduction/nextcloud-vue`'s EUPL-compatible NL-government packs (RVO, OpenGemeenten, Gemeente Den Haag) plus 1038 SVG icons from the French-government DSFR pack (`@gouvfr/dsfr`, Etalab-2.0) — 2526 icons total — plus 41 organization and example logos, for use across all Nextcloud apps
+- **NL-Government and French-Government Icons**: Includes 1488 SVG icons sourced from `@conduction/nextcloud-vue`'s EUPL-compatible NL-government packs (RVO, OpenGemeenten, Gemeente Den Haag) plus 1038 SVG icons from the French-government DSFR pack (`@gouvfr/dsfr`, Etalab-2.0) — 2526 icons total — plus 57 organization and example logos, for use across all Nextcloud apps
- **Theme-switchable iconography**: The icon pack an app resolves through nldesign travels with the active design system — a French-government (`lasuite`) theme serves the DSFR pack, a Dutch-government theme serves the RVO/OpenGemeenten/Den Haag packs — resolved via `DesignSystemService` and advertised on the public capability (`iconPacks`). See `img/ICONS.md`.
## Icons
-The app includes **2526 icons** across four government icon sets and **41 logos**:
+The app includes **2526 icons** across four government icon sets and **57 logos**:
- RVO, OpenGemeenten, Gemeente Den Haag — **1488 icons** (CC0-1.0 / CC0-1.0 / EUPL-1.2), materialized from `@conduction/nextcloud-vue`
- DSFR (Système de Design de l'État) — **1038 icons** (**Etalab-2.0**), materialized from `@gouvfr/dsfr`
diff --git a/REUSE.toml b/REUSE.toml
index 653afa1aa..793fa4740 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -83,7 +83,10 @@ SPDX-FileCopyrightText = "2022 The Figtree Project Authors (https://github.com/e
SPDX-License-Identifier = "OFL-1.1"
[[annotations]]
-path = "css/fonts/ibm-plex-mono-*"
+path = [
+ "css/fonts/ibm-plex-mono-*",
+ "css/systems/nldesign/fonts/ibm-plex-mono-*",
+]
precedence = "override"
SPDX-FileCopyrightText = "2017 IBM Corp. with Reserved Font Name \"Plex\" (https://github.com/IBM/plex)"
SPDX-License-Identifier = "OFL-1.1"
@@ -134,6 +137,36 @@ precedence = "override"
SPDX-FileCopyrightText = "2017 IBM Corp. with Reserved Font Name \"Plex\" (https://github.com/IBM/plex)"
SPDX-License-Identifier = "OFL-1.1"
+# The typefaces of the four school sets (openspec/changes/school-token-sets).
+[[annotations]]
+path = [
+ "css/fonts/lexend-*",
+ "css/systems/nldesign/fonts/lexend-*",
+]
+precedence = "override"
+SPDX-FileCopyrightText = "2019 The Lexend Project Authors (https://github.com/googlefonts/lexend)"
+SPDX-License-Identifier = "OFL-1.1"
+
+[[annotations]]
+path = [
+ "css/fonts/red-hat-display-*",
+ "css/systems/nldesign/fonts/red-hat-display-*",
+ "css/fonts/red-hat-text-*",
+ "css/systems/nldesign/fonts/red-hat-text-*",
+]
+precedence = "override"
+SPDX-FileCopyrightText = "2024 The Red Hat Project Authors (https://github.com/RedHatOfficial/RedHatFont)"
+SPDX-License-Identifier = "OFL-1.1"
+
+[[annotations]]
+path = [
+ "css/fonts/barlow-*",
+ "css/systems/nldesign/fonts/barlow-*",
+]
+precedence = "override"
+SPDX-FileCopyrightText = "2017 The Barlow Project Authors (https://github.com/jpt/barlow)"
+SPDX-License-Identifier = "OFL-1.1"
+
# Intel Clear Sans is Apache-2.0, not OFL, so it travels with
# LICENSES/Apache-2.0.txt and its own APACHE-2.0.txt beside the binaries.
[[annotations]]
@@ -163,6 +196,9 @@ SPDX-FileCopyrightText = [
"2011 The Roboto Project Authors (https://github.com/googlefonts/roboto-classic)",
"2017 IBM Corp. with Reserved Font Name \"Plex\" (https://github.com/IBM/plex)",
"2022 The Figtree Project Authors (https://github.com/erikdkennedy/figtree)",
+ "2019 The Lexend Project Authors (https://github.com/googlefonts/lexend)",
+ "2024 The Red Hat Project Authors (https://github.com/RedHatOfficial/RedHatFont)",
+ "2017 The Barlow Project Authors (https://github.com/jpt/barlow)",
]
SPDX-License-Identifier = "OFL-1.1"
diff --git a/css/brand-stripe.css b/css/brand-stripe.css
index f3414f160..4c1f583f4 100644
--- a/css/brand-stripe.css
+++ b/css/brand-stripe.css
@@ -19,6 +19,18 @@
* A set that declares none gets three equal bands in its primary colour, the
* primary hover and the primary again, 4px high.
*
+ * A MOTIF THAT IS NOT THREE BANDS. A set may name an image of its own in
+ *
+ * --nldesign-brand-stripe-image any background-image value
+ *
+ * and the stripe draws that instead of the three bands, in the same box and at
+ * the same height: the hanging twigs of wilgenboom, the canal and its bank of
+ * vaartveld, the slanted cut of esdoornveen, the five steps of the
+ * warmtepompacademie (openspec/changes/school-token-sets). The three colours
+ * stay declared, because the component library's stripe below reads only
+ * those. An image named by url() must be a data: URI: a relative path would
+ * resolve against this stylesheet, not against the token file that names it.
+ *
* IT SITS INSIDE THE BAR, NOT UNDER IT. Nextcloud places the content exactly
* one header height from the top, so a stripe hanging below the bar would lie
* over the first pixels of every app, and raising `--header-height` moves
@@ -78,12 +90,15 @@
z-index: 1;
height: var(--nldesign-brand-stripe-height, 4px);
pointer-events: none;
- background-image: linear-gradient(
- to right,
- var(--thematiq-stripe-color-1) 0 var(--thematiq-stripe-stop-1),
- var(--thematiq-stripe-color-2) var(--thematiq-stripe-stop-1)
- var(--thematiq-stripe-stop-2),
- var(--thematiq-stripe-color-3) var(--thematiq-stripe-stop-2) 100%
+ background-image: var(
+ --nldesign-brand-stripe-image,
+ linear-gradient(
+ to right,
+ var(--thematiq-stripe-color-1) 0 var(--thematiq-stripe-stop-1),
+ var(--thematiq-stripe-color-2) var(--thematiq-stripe-stop-1)
+ var(--thematiq-stripe-stop-2),
+ var(--thematiq-stripe-color-3) var(--thematiq-stripe-stop-2) 100%
+ )
);
}
diff --git a/css/fonts.css b/css/fonts.css
index 55b44c263..6a03714fc 100644
--- a/css/fonts.css
+++ b/css/fonts.css
@@ -288,6 +288,7 @@
* IBM Plex Sans — OFL-1.1.
* Copyright 2017 IBM Corp. with Reserved Font Name "Plex" (https://github.com/IBM/plex).
* From @fontsource/ibm-plex-sans 5.3.0, latin subset.
+ * Medium (500) is there for esdoornveen, whose design uses four weights.
*/
@font-face {
@@ -300,6 +301,16 @@
font-display: swap;
}
+@font-face {
+ font-family: 'IBM Plex Sans';
+ src:
+ local('IBM Plex Sans Medium'),
+ url('fonts/ibm-plex-sans-latin-500-normal.woff2') format('woff2');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
@font-face {
font-family: 'IBM Plex Sans';
src:
@@ -320,6 +331,238 @@
font-display: swap;
}
+/*
+ * IBM Plex Mono — OFL-1.1.
+ * Copyright 2017 IBM Corp. with Reserved Font Name "Plex" (https://github.com/IBM/plex).
+ * From @fontsource/ibm-plex-mono 5.3.0, latin subset.
+ * Codes such as crebo numbers and exam codes in the esdoornveen set. The 400 file keeps the name css/fonts-conduction.css has always linked; it is byte-identical to the package file ibm-plex-mono-latin-400-normal.woff2.
+ */
+
+@font-face {
+ font-family: 'IBM Plex Mono';
+ src:
+ local('IBM Plex Mono'),
+ url('fonts/ibm-plex-mono-latin-400.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'IBM Plex Mono';
+ src:
+ local('IBM Plex Mono Medium'),
+ url('fonts/ibm-plex-mono-latin-500-normal.woff2') format('woff2');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+/*
+ * Lexend — OFL-1.1.
+ * Copyright 2019 The Lexend Project Authors (https://github.com/googlefonts/lexend).
+ * From @fontsource/lexend 5.3.0, latin subset.
+ * Named by the wilgenboom set.
+ */
+
+@font-face {
+ font-family: 'Lexend';
+ src:
+ local('Lexend'),
+ url('fonts/lexend-latin-400-normal.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Lexend';
+ src:
+ local('Lexend Medium'),
+ url('fonts/lexend-latin-500-normal.woff2') format('woff2');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Lexend';
+ src:
+ local('Lexend SemiBold'),
+ url('fonts/lexend-latin-600-normal.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Lexend';
+ src:
+ local('Lexend Bold'),
+ url('fonts/lexend-latin-700-normal.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
+/*
+ * Red Hat Display — OFL-1.1.
+ * Copyright 2024 The Red Hat Project Authors (https://github.com/RedHatOfficial/RedHatFont).
+ * From @fontsource/red-hat-display 5.3.0, latin subset.
+ * The heading face of the vaartveld set.
+ */
+
+@font-face {
+ font-family: 'Red Hat Display';
+ src:
+ local('Red Hat Display SemiBold'),
+ url('fonts/red-hat-display-latin-600-normal.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Red Hat Display';
+ src:
+ local('Red Hat Display Bold'),
+ url('fonts/red-hat-display-latin-700-normal.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Red Hat Display';
+ src:
+ local('Red Hat Display ExtraBold'),
+ url('fonts/red-hat-display-latin-800-normal.woff2') format('woff2');
+ font-weight: 800;
+ font-style: normal;
+ font-display: swap;
+}
+
+/*
+ * Red Hat Text — OFL-1.1.
+ * Copyright 2024 The Red Hat Project Authors (https://github.com/RedHatOfficial/RedHatFont).
+ * From @fontsource/red-hat-text 5.3.0, latin subset.
+ * The text face of the vaartveld set.
+ */
+
+@font-face {
+ font-family: 'Red Hat Text';
+ src:
+ local('Red Hat Text'),
+ url('fonts/red-hat-text-latin-400-normal.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Red Hat Text';
+ src:
+ local('Red Hat Text Medium'),
+ url('fonts/red-hat-text-latin-500-normal.woff2') format('woff2');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Red Hat Text';
+ src:
+ local('Red Hat Text SemiBold'),
+ url('fonts/red-hat-text-latin-600-normal.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Red Hat Text';
+ src:
+ local('Red Hat Text Bold'),
+ url('fonts/red-hat-text-latin-700-normal.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
+/*
+ * Barlow — OFL-1.1.
+ * Copyright 2017 The Barlow Project Authors (https://github.com/jpt/barlow).
+ * From @fontsource/barlow 5.3.0, latin subset.
+ * The text face of the warmtepompacademie set.
+ */
+
+@font-face {
+ font-family: 'Barlow';
+ src:
+ local('Barlow'),
+ url('fonts/barlow-latin-400-normal.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Barlow';
+ src:
+ local('Barlow Medium'),
+ url('fonts/barlow-latin-500-normal.woff2') format('woff2');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Barlow';
+ src:
+ local('Barlow SemiBold'),
+ url('fonts/barlow-latin-600-normal.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Barlow';
+ src:
+ local('Barlow Bold'),
+ url('fonts/barlow-latin-700-normal.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
+/*
+ * Barlow Semi Condensed — OFL-1.1.
+ * Copyright 2017 The Barlow Project Authors (https://github.com/jpt/barlow).
+ * From @fontsource/barlow-semi-condensed 5.3.0, latin subset.
+ * The heading face of the warmtepompacademie set.
+ */
+
+@font-face {
+ font-family: 'Barlow Semi Condensed';
+ src:
+ local('Barlow Semi Condensed SemiBold'),
+ url('fonts/barlow-semi-condensed-latin-600-normal.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Barlow Semi Condensed';
+ src:
+ local('Barlow Semi Condensed Bold'),
+ url('fonts/barlow-semi-condensed-latin-700-normal.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
/*
* Clear Sans — Apache-2.0.
* Copyright 2012 Intel Corporation (https://github.com/intel/clear-sans).
diff --git a/css/fonts/OFL.txt b/css/fonts/OFL.txt
index c12e6b004..6073a5541 100644
--- a/css/fonts/OFL.txt
+++ b/css/fonts/OFL.txt
@@ -5,8 +5,13 @@ Open Sans: Copyright 2020 The Open Sans Project Authors (https://github.com/goog
Lato: Copyright 2010-2011 by tyPoland Lukasz Dziedzic (team@latofonts.com) with Reserved Font Name "Lato"
Roboto: Copyright 2011 The Roboto Project Authors (https://github.com/googlefonts/roboto-classic)
IBM Plex Sans: Copyright 2017 IBM Corp. with Reserved Font Name "Plex" (https://github.com/IBM/plex)
-Figtree: Copyright 2022 The Figtree Project Authors (https://github.com/erikdkennedy/figtree)
IBM Plex Mono: Copyright 2017 IBM Corp. with Reserved Font Name "Plex" (https://github.com/IBM/plex)
+Lexend: Copyright 2019 The Lexend Project Authors (https://github.com/googlefonts/lexend)
+Red Hat Display: Copyright 2024 The Red Hat Project Authors (https://github.com/RedHatOfficial/RedHatFont)
+Red Hat Text: Copyright 2024 The Red Hat Project Authors (https://github.com/RedHatOfficial/RedHatFont)
+Barlow: Copyright 2017 The Barlow Project Authors (https://github.com/jpt/barlow)
+Barlow Semi Condensed: Copyright 2017 The Barlow Project Authors (https://github.com/jpt/barlow)
+Figtree: Copyright 2022 The Figtree Project Authors (https://github.com/erikdkennedy/figtree)
licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
diff --git a/css/fonts/barlow-latin-400-normal.woff2 b/css/fonts/barlow-latin-400-normal.woff2
new file mode 100644
index 000000000..3914af460
Binary files /dev/null and b/css/fonts/barlow-latin-400-normal.woff2 differ
diff --git a/css/fonts/barlow-latin-500-normal.woff2 b/css/fonts/barlow-latin-500-normal.woff2
new file mode 100644
index 000000000..b1d06c6db
Binary files /dev/null and b/css/fonts/barlow-latin-500-normal.woff2 differ
diff --git a/css/fonts/barlow-latin-600-normal.woff2 b/css/fonts/barlow-latin-600-normal.woff2
new file mode 100644
index 000000000..b1a019f9d
Binary files /dev/null and b/css/fonts/barlow-latin-600-normal.woff2 differ
diff --git a/css/fonts/barlow-latin-700-normal.woff2 b/css/fonts/barlow-latin-700-normal.woff2
new file mode 100644
index 000000000..4ee6cd865
Binary files /dev/null and b/css/fonts/barlow-latin-700-normal.woff2 differ
diff --git a/css/fonts/barlow-semi-condensed-latin-600-normal.woff2 b/css/fonts/barlow-semi-condensed-latin-600-normal.woff2
new file mode 100644
index 000000000..613e861ac
Binary files /dev/null and b/css/fonts/barlow-semi-condensed-latin-600-normal.woff2 differ
diff --git a/css/fonts/barlow-semi-condensed-latin-700-normal.woff2 b/css/fonts/barlow-semi-condensed-latin-700-normal.woff2
new file mode 100644
index 000000000..d96ddc1d7
Binary files /dev/null and b/css/fonts/barlow-semi-condensed-latin-700-normal.woff2 differ
diff --git a/css/fonts/ibm-plex-mono-latin-500-normal.woff2 b/css/fonts/ibm-plex-mono-latin-500-normal.woff2
new file mode 100644
index 000000000..090f82f7e
Binary files /dev/null and b/css/fonts/ibm-plex-mono-latin-500-normal.woff2 differ
diff --git a/css/fonts/ibm-plex-sans-latin-500-normal.woff2 b/css/fonts/ibm-plex-sans-latin-500-normal.woff2
new file mode 100644
index 000000000..6d5527eef
Binary files /dev/null and b/css/fonts/ibm-plex-sans-latin-500-normal.woff2 differ
diff --git a/css/fonts/lexend-latin-400-normal.woff2 b/css/fonts/lexend-latin-400-normal.woff2
new file mode 100644
index 000000000..a65647312
Binary files /dev/null and b/css/fonts/lexend-latin-400-normal.woff2 differ
diff --git a/css/fonts/lexend-latin-500-normal.woff2 b/css/fonts/lexend-latin-500-normal.woff2
new file mode 100644
index 000000000..57a4bae04
Binary files /dev/null and b/css/fonts/lexend-latin-500-normal.woff2 differ
diff --git a/css/fonts/lexend-latin-600-normal.woff2 b/css/fonts/lexend-latin-600-normal.woff2
new file mode 100644
index 000000000..38cdff617
Binary files /dev/null and b/css/fonts/lexend-latin-600-normal.woff2 differ
diff --git a/css/fonts/lexend-latin-700-normal.woff2 b/css/fonts/lexend-latin-700-normal.woff2
new file mode 100644
index 000000000..1639b3445
Binary files /dev/null and b/css/fonts/lexend-latin-700-normal.woff2 differ
diff --git a/css/fonts/red-hat-display-latin-600-normal.woff2 b/css/fonts/red-hat-display-latin-600-normal.woff2
new file mode 100644
index 000000000..b7d73a0ce
Binary files /dev/null and b/css/fonts/red-hat-display-latin-600-normal.woff2 differ
diff --git a/css/fonts/red-hat-display-latin-700-normal.woff2 b/css/fonts/red-hat-display-latin-700-normal.woff2
new file mode 100644
index 000000000..1e9484f34
Binary files /dev/null and b/css/fonts/red-hat-display-latin-700-normal.woff2 differ
diff --git a/css/fonts/red-hat-display-latin-800-normal.woff2 b/css/fonts/red-hat-display-latin-800-normal.woff2
new file mode 100644
index 000000000..a162d3e9a
Binary files /dev/null and b/css/fonts/red-hat-display-latin-800-normal.woff2 differ
diff --git a/css/fonts/red-hat-text-latin-400-normal.woff2 b/css/fonts/red-hat-text-latin-400-normal.woff2
new file mode 100644
index 000000000..f679845ee
Binary files /dev/null and b/css/fonts/red-hat-text-latin-400-normal.woff2 differ
diff --git a/css/fonts/red-hat-text-latin-500-normal.woff2 b/css/fonts/red-hat-text-latin-500-normal.woff2
new file mode 100644
index 000000000..3881ce0b9
Binary files /dev/null and b/css/fonts/red-hat-text-latin-500-normal.woff2 differ
diff --git a/css/fonts/red-hat-text-latin-600-normal.woff2 b/css/fonts/red-hat-text-latin-600-normal.woff2
new file mode 100644
index 000000000..c963fbd1f
Binary files /dev/null and b/css/fonts/red-hat-text-latin-600-normal.woff2 differ
diff --git a/css/fonts/red-hat-text-latin-700-normal.woff2 b/css/fonts/red-hat-text-latin-700-normal.woff2
new file mode 100644
index 000000000..ff78f0523
Binary files /dev/null and b/css/fonts/red-hat-text-latin-700-normal.woff2 differ
diff --git a/css/public-bridge.css b/css/public-bridge.css
index 11166365a..d1d54bbea 100644
--- a/css/public-bridge.css
+++ b/css/public-bridge.css
@@ -23,8 +23,8 @@
*
* MEASURED COVERAGE (a test recomputes these from token-sets.json and
* css/tokens/, and fails when they drift):
- * coverage: listed=59 roleLayer=26 nldesignOnly=11 denhaagComponents=18
- * Of the listed sets, 26 carry the full `--utrecht-*` role layer, 11 declare
+ * coverage: listed=63 roleLayer=26 nldesignOnly=15 denhaagComponents=18
+ * Of the listed sets, 26 carry the full `--utrecht-*` role layer, 15 declare
* only `--nldesign-*`, and 18 declare Den Haag component properties. Two sets
* declare a case card property of their own, `cunningham` and `denhaag`; the
* Den Haag section at the end of this block gives every other set one, and
@@ -71,11 +71,15 @@
* reads its OWN token — setting only `--utrecht-heading-color` leaves every
* numbered level unstyled, which is how a page ends up with one styled
* heading and five browser-default ones.
+ *
+ * A set with a heading face of its own names it in
+ * `--nldesign-component-heading-font-family`, the token Nextcloud's
+ * headings already read (vaartveld: Red Hat Display over Red Hat Text).
+ * A set that names none keeps its one family for both.
*/
--utrecht-heading-font-family: var(
- --nldesign-font-family,
- system-ui,
- sans-serif
+ --nldesign-component-heading-font-family,
+ var(--nldesign-font-family, system-ui, sans-serif)
);
--utrecht-heading-color: var(--nldesign-color-text, #1b1b23);
--utrecht-heading-1-color: var(--nldesign-color-text, #1b1b23);
@@ -85,21 +89,45 @@
--utrecht-heading-5-color: var(--nldesign-color-text, #1b1b23);
--utrecht-heading-6-color: var(--nldesign-color-text, #1b1b23);
--utrecht-heading-1-font-family: var(
- --nldesign-font-family,
- system-ui,
- sans-serif
+ --nldesign-component-heading-font-family,
+ var(--nldesign-font-family, system-ui, sans-serif)
);
--utrecht-heading-2-font-family: var(
- --nldesign-font-family,
- system-ui,
- sans-serif
+ --nldesign-component-heading-font-family,
+ var(--nldesign-font-family, system-ui, sans-serif)
);
--utrecht-heading-3-font-family: var(
- --nldesign-font-family,
- system-ui,
- sans-serif
+ --nldesign-component-heading-font-family,
+ var(--nldesign-font-family, system-ui, sans-serif)
);
+ /*
+ * Website corners (openspec/changes/school-token-sets).
+ *
+ * The workplace keeps Nextcloud's radius scale (8px controls, 12px
+ * cards), so a set's `--nldesign-border-radius` cannot also be the
+ * website's. A set whose website is rounder or squarer than its workplace
+ * names the website's two radii here, and only this file reads them: it
+ * is linked by a public portal and never on an instance page.
+ *
+ * --nldesign-website-border-radius buttons and form fields
+ * --nldesign-website-border-radius-large cards, dialogs and messages
+ *
+ * NO FALLBACK, ON PURPOSE. For a set that names neither, each role below
+ * resolves to the guaranteed-invalid value, which a consumer's
+ * `var(--utrecht-button-border-radius, 8px)` treats exactly as an unset
+ * property, so its own fallback still applies and no existing portal
+ * changes. A set that declares a role itself loads after this file and
+ * keeps its value.
+ */
+ --utrecht-button-border-radius: var(--nldesign-website-border-radius);
+ --utrecht-textbox-border-radius: var(--nldesign-website-border-radius);
+ --utrecht-textarea-border-radius: var(--nldesign-website-border-radius);
+ --utrecht-select-border-radius: var(--nldesign-website-border-radius);
+ --utrecht-form-control-border-radius: var(--nldesign-website-border-radius);
+ --utrecht-border-radius-md: var(--nldesign-website-border-radius-large);
+ --utrecht-alert-border-radius: var(--nldesign-website-border-radius-large);
+
/* Links */
--utrecht-link-color: var(
--nldesign-color-link,
diff --git a/css/systems/nldesign/fonts.css b/css/systems/nldesign/fonts.css
index 55b44c263..6a03714fc 100644
--- a/css/systems/nldesign/fonts.css
+++ b/css/systems/nldesign/fonts.css
@@ -288,6 +288,7 @@
* IBM Plex Sans — OFL-1.1.
* Copyright 2017 IBM Corp. with Reserved Font Name "Plex" (https://github.com/IBM/plex).
* From @fontsource/ibm-plex-sans 5.3.0, latin subset.
+ * Medium (500) is there for esdoornveen, whose design uses four weights.
*/
@font-face {
@@ -300,6 +301,16 @@
font-display: swap;
}
+@font-face {
+ font-family: 'IBM Plex Sans';
+ src:
+ local('IBM Plex Sans Medium'),
+ url('fonts/ibm-plex-sans-latin-500-normal.woff2') format('woff2');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
@font-face {
font-family: 'IBM Plex Sans';
src:
@@ -320,6 +331,238 @@
font-display: swap;
}
+/*
+ * IBM Plex Mono — OFL-1.1.
+ * Copyright 2017 IBM Corp. with Reserved Font Name "Plex" (https://github.com/IBM/plex).
+ * From @fontsource/ibm-plex-mono 5.3.0, latin subset.
+ * Codes such as crebo numbers and exam codes in the esdoornveen set. The 400 file keeps the name css/fonts-conduction.css has always linked; it is byte-identical to the package file ibm-plex-mono-latin-400-normal.woff2.
+ */
+
+@font-face {
+ font-family: 'IBM Plex Mono';
+ src:
+ local('IBM Plex Mono'),
+ url('fonts/ibm-plex-mono-latin-400.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'IBM Plex Mono';
+ src:
+ local('IBM Plex Mono Medium'),
+ url('fonts/ibm-plex-mono-latin-500-normal.woff2') format('woff2');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+/*
+ * Lexend — OFL-1.1.
+ * Copyright 2019 The Lexend Project Authors (https://github.com/googlefonts/lexend).
+ * From @fontsource/lexend 5.3.0, latin subset.
+ * Named by the wilgenboom set.
+ */
+
+@font-face {
+ font-family: 'Lexend';
+ src:
+ local('Lexend'),
+ url('fonts/lexend-latin-400-normal.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Lexend';
+ src:
+ local('Lexend Medium'),
+ url('fonts/lexend-latin-500-normal.woff2') format('woff2');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Lexend';
+ src:
+ local('Lexend SemiBold'),
+ url('fonts/lexend-latin-600-normal.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Lexend';
+ src:
+ local('Lexend Bold'),
+ url('fonts/lexend-latin-700-normal.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
+/*
+ * Red Hat Display — OFL-1.1.
+ * Copyright 2024 The Red Hat Project Authors (https://github.com/RedHatOfficial/RedHatFont).
+ * From @fontsource/red-hat-display 5.3.0, latin subset.
+ * The heading face of the vaartveld set.
+ */
+
+@font-face {
+ font-family: 'Red Hat Display';
+ src:
+ local('Red Hat Display SemiBold'),
+ url('fonts/red-hat-display-latin-600-normal.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Red Hat Display';
+ src:
+ local('Red Hat Display Bold'),
+ url('fonts/red-hat-display-latin-700-normal.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Red Hat Display';
+ src:
+ local('Red Hat Display ExtraBold'),
+ url('fonts/red-hat-display-latin-800-normal.woff2') format('woff2');
+ font-weight: 800;
+ font-style: normal;
+ font-display: swap;
+}
+
+/*
+ * Red Hat Text — OFL-1.1.
+ * Copyright 2024 The Red Hat Project Authors (https://github.com/RedHatOfficial/RedHatFont).
+ * From @fontsource/red-hat-text 5.3.0, latin subset.
+ * The text face of the vaartveld set.
+ */
+
+@font-face {
+ font-family: 'Red Hat Text';
+ src:
+ local('Red Hat Text'),
+ url('fonts/red-hat-text-latin-400-normal.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Red Hat Text';
+ src:
+ local('Red Hat Text Medium'),
+ url('fonts/red-hat-text-latin-500-normal.woff2') format('woff2');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Red Hat Text';
+ src:
+ local('Red Hat Text SemiBold'),
+ url('fonts/red-hat-text-latin-600-normal.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Red Hat Text';
+ src:
+ local('Red Hat Text Bold'),
+ url('fonts/red-hat-text-latin-700-normal.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
+/*
+ * Barlow — OFL-1.1.
+ * Copyright 2017 The Barlow Project Authors (https://github.com/jpt/barlow).
+ * From @fontsource/barlow 5.3.0, latin subset.
+ * The text face of the warmtepompacademie set.
+ */
+
+@font-face {
+ font-family: 'Barlow';
+ src:
+ local('Barlow'),
+ url('fonts/barlow-latin-400-normal.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Barlow';
+ src:
+ local('Barlow Medium'),
+ url('fonts/barlow-latin-500-normal.woff2') format('woff2');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Barlow';
+ src:
+ local('Barlow SemiBold'),
+ url('fonts/barlow-latin-600-normal.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Barlow';
+ src:
+ local('Barlow Bold'),
+ url('fonts/barlow-latin-700-normal.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
+/*
+ * Barlow Semi Condensed — OFL-1.1.
+ * Copyright 2017 The Barlow Project Authors (https://github.com/jpt/barlow).
+ * From @fontsource/barlow-semi-condensed 5.3.0, latin subset.
+ * The heading face of the warmtepompacademie set.
+ */
+
+@font-face {
+ font-family: 'Barlow Semi Condensed';
+ src:
+ local('Barlow Semi Condensed SemiBold'),
+ url('fonts/barlow-semi-condensed-latin-600-normal.woff2') format('woff2');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Barlow Semi Condensed';
+ src:
+ local('Barlow Semi Condensed Bold'),
+ url('fonts/barlow-semi-condensed-latin-700-normal.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
/*
* Clear Sans — Apache-2.0.
* Copyright 2012 Intel Corporation (https://github.com/intel/clear-sans).
diff --git a/css/systems/nldesign/fonts/OFL.txt b/css/systems/nldesign/fonts/OFL.txt
index 71596c328..6073a5541 100644
--- a/css/systems/nldesign/fonts/OFL.txt
+++ b/css/systems/nldesign/fonts/OFL.txt
@@ -5,6 +5,12 @@ Open Sans: Copyright 2020 The Open Sans Project Authors (https://github.com/goog
Lato: Copyright 2010-2011 by tyPoland Lukasz Dziedzic (team@latofonts.com) with Reserved Font Name "Lato"
Roboto: Copyright 2011 The Roboto Project Authors (https://github.com/googlefonts/roboto-classic)
IBM Plex Sans: Copyright 2017 IBM Corp. with Reserved Font Name "Plex" (https://github.com/IBM/plex)
+IBM Plex Mono: Copyright 2017 IBM Corp. with Reserved Font Name "Plex" (https://github.com/IBM/plex)
+Lexend: Copyright 2019 The Lexend Project Authors (https://github.com/googlefonts/lexend)
+Red Hat Display: Copyright 2024 The Red Hat Project Authors (https://github.com/RedHatOfficial/RedHatFont)
+Red Hat Text: Copyright 2024 The Red Hat Project Authors (https://github.com/RedHatOfficial/RedHatFont)
+Barlow: Copyright 2017 The Barlow Project Authors (https://github.com/jpt/barlow)
+Barlow Semi Condensed: Copyright 2017 The Barlow Project Authors (https://github.com/jpt/barlow)
Figtree: Copyright 2022 The Figtree Project Authors (https://github.com/erikdkennedy/figtree)
licensed under the SIL Open Font License, Version 1.1.
diff --git a/css/systems/nldesign/fonts/barlow-latin-400-normal.woff2 b/css/systems/nldesign/fonts/barlow-latin-400-normal.woff2
new file mode 100644
index 000000000..3914af460
Binary files /dev/null and b/css/systems/nldesign/fonts/barlow-latin-400-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/barlow-latin-500-normal.woff2 b/css/systems/nldesign/fonts/barlow-latin-500-normal.woff2
new file mode 100644
index 000000000..b1d06c6db
Binary files /dev/null and b/css/systems/nldesign/fonts/barlow-latin-500-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/barlow-latin-600-normal.woff2 b/css/systems/nldesign/fonts/barlow-latin-600-normal.woff2
new file mode 100644
index 000000000..b1a019f9d
Binary files /dev/null and b/css/systems/nldesign/fonts/barlow-latin-600-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/barlow-latin-700-normal.woff2 b/css/systems/nldesign/fonts/barlow-latin-700-normal.woff2
new file mode 100644
index 000000000..4ee6cd865
Binary files /dev/null and b/css/systems/nldesign/fonts/barlow-latin-700-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/barlow-semi-condensed-latin-600-normal.woff2 b/css/systems/nldesign/fonts/barlow-semi-condensed-latin-600-normal.woff2
new file mode 100644
index 000000000..613e861ac
Binary files /dev/null and b/css/systems/nldesign/fonts/barlow-semi-condensed-latin-600-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/barlow-semi-condensed-latin-700-normal.woff2 b/css/systems/nldesign/fonts/barlow-semi-condensed-latin-700-normal.woff2
new file mode 100644
index 000000000..d96ddc1d7
Binary files /dev/null and b/css/systems/nldesign/fonts/barlow-semi-condensed-latin-700-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/ibm-plex-mono-latin-400.woff2 b/css/systems/nldesign/fonts/ibm-plex-mono-latin-400.woff2
new file mode 100644
index 000000000..0804aaff9
Binary files /dev/null and b/css/systems/nldesign/fonts/ibm-plex-mono-latin-400.woff2 differ
diff --git a/css/systems/nldesign/fonts/ibm-plex-mono-latin-500-normal.woff2 b/css/systems/nldesign/fonts/ibm-plex-mono-latin-500-normal.woff2
new file mode 100644
index 000000000..090f82f7e
Binary files /dev/null and b/css/systems/nldesign/fonts/ibm-plex-mono-latin-500-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/ibm-plex-sans-latin-500-normal.woff2 b/css/systems/nldesign/fonts/ibm-plex-sans-latin-500-normal.woff2
new file mode 100644
index 000000000..6d5527eef
Binary files /dev/null and b/css/systems/nldesign/fonts/ibm-plex-sans-latin-500-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/lexend-latin-400-normal.woff2 b/css/systems/nldesign/fonts/lexend-latin-400-normal.woff2
new file mode 100644
index 000000000..a65647312
Binary files /dev/null and b/css/systems/nldesign/fonts/lexend-latin-400-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/lexend-latin-500-normal.woff2 b/css/systems/nldesign/fonts/lexend-latin-500-normal.woff2
new file mode 100644
index 000000000..57a4bae04
Binary files /dev/null and b/css/systems/nldesign/fonts/lexend-latin-500-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/lexend-latin-600-normal.woff2 b/css/systems/nldesign/fonts/lexend-latin-600-normal.woff2
new file mode 100644
index 000000000..38cdff617
Binary files /dev/null and b/css/systems/nldesign/fonts/lexend-latin-600-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/lexend-latin-700-normal.woff2 b/css/systems/nldesign/fonts/lexend-latin-700-normal.woff2
new file mode 100644
index 000000000..1639b3445
Binary files /dev/null and b/css/systems/nldesign/fonts/lexend-latin-700-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/red-hat-display-latin-600-normal.woff2 b/css/systems/nldesign/fonts/red-hat-display-latin-600-normal.woff2
new file mode 100644
index 000000000..b7d73a0ce
Binary files /dev/null and b/css/systems/nldesign/fonts/red-hat-display-latin-600-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/red-hat-display-latin-700-normal.woff2 b/css/systems/nldesign/fonts/red-hat-display-latin-700-normal.woff2
new file mode 100644
index 000000000..1e9484f34
Binary files /dev/null and b/css/systems/nldesign/fonts/red-hat-display-latin-700-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/red-hat-display-latin-800-normal.woff2 b/css/systems/nldesign/fonts/red-hat-display-latin-800-normal.woff2
new file mode 100644
index 000000000..a162d3e9a
Binary files /dev/null and b/css/systems/nldesign/fonts/red-hat-display-latin-800-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/red-hat-text-latin-400-normal.woff2 b/css/systems/nldesign/fonts/red-hat-text-latin-400-normal.woff2
new file mode 100644
index 000000000..f679845ee
Binary files /dev/null and b/css/systems/nldesign/fonts/red-hat-text-latin-400-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/red-hat-text-latin-500-normal.woff2 b/css/systems/nldesign/fonts/red-hat-text-latin-500-normal.woff2
new file mode 100644
index 000000000..3881ce0b9
Binary files /dev/null and b/css/systems/nldesign/fonts/red-hat-text-latin-500-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/red-hat-text-latin-600-normal.woff2 b/css/systems/nldesign/fonts/red-hat-text-latin-600-normal.woff2
new file mode 100644
index 000000000..c963fbd1f
Binary files /dev/null and b/css/systems/nldesign/fonts/red-hat-text-latin-600-normal.woff2 differ
diff --git a/css/systems/nldesign/fonts/red-hat-text-latin-700-normal.woff2 b/css/systems/nldesign/fonts/red-hat-text-latin-700-normal.woff2
new file mode 100644
index 000000000..ff78f0523
Binary files /dev/null and b/css/systems/nldesign/fonts/red-hat-text-latin-700-normal.woff2 differ
diff --git a/css/token-overrides/esdoornveen.css b/css/token-overrides/esdoornveen.css
new file mode 100644
index 000000000..12124c8e6
--- /dev/null
+++ b/css/token-overrides/esdoornveen.css
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: EUPL-1.2
+ SPDX-FileCopyrightText: 2026 Conduction B.V.
+
+ Esdoornveen, mbo college overrides: the dark page, the dark workspace and the
+ login logo, as css/token-overrides/zuiddrecht.css sets them for zuiddrecht
+ and for the same reasons (openspec/changes/school-token-sets).
+
+ 1. THE PAGE BACKGROUND. Nextcloud keeps the theming background (#F5F6F8)
+ in the dark, so a dark workplace would sit in a light grey frame. In the
+ dark the page takes the colour of the workspace.
+
+ 2. THE WORKSPACE. The generator turns the light #F5F6F8 into a grey that is
+ lighter than Nextcloud's dark cards (#171717), so the cards would sink
+ into it. In the dark the workspace is #121315, below the cards.
+
+ 3. WHAT THE GENERATOR DERIVES BELOW AA. Measured by
+ tests/vitest/schoolTokenSets.spec.js; each is set by hand here:
+ - --nldesign-color-info: the generator put the info colour at #966bc9, 4.47:1 on the dark cards; it takes the dark link colour, as info equals the link in the light
+ - --nldesign-color-info-rgb: the same colour as channels
+ - --nldesign-component-navigation-active-background-color: the generated #d14274 carries the dark label #111111 at 4.26:1 where the entry is filled solid; #d94d7f carries it at 4.78:1
+ - --nldesign-component-navigation-active-color: the generated #e36390 is 4.42:1 on the hovered wash; #ec86ab is 6.14:1 on the wash and 5.67:1 hovered
+
+ This lives outside `css/tokens/` because a shipped token file is one flat
+ `:root { }` block with no at-rule (TokenCssShapeTest). The selectors start
+ with `:root` so they outrank the generated dark file, which loads after
+ this one. */
+@media (prefers-color-scheme: dark) {
+ :root
+ body:not([data-theme-light]):not([data-theme-dark]):not(
+ [data-theme-light-highcontrast]
+ ):not([data-theme-dark-highcontrast]) {
+ --color-background-plain: #121315;
+ --color-background-plain-text: var(--color-main-text);
+ --nldesign-component-content-surface-background-color: #121315;
+ --nldesign-color-info: #d8c8eb;
+ --nldesign-color-info-rgb: 216, 200, 235;
+ --nldesign-component-navigation-active-background-color: #d94d7f;
+ --nldesign-component-navigation-active-color: #ec86ab;
+ }
+}
+
+:root body[data-theme-dark],
+:root body[data-themes*='dark'] {
+ --color-background-plain: #121315;
+ --color-background-plain-text: var(--color-main-text);
+ --nldesign-component-content-surface-background-color: #121315;
+ --nldesign-color-info: #d8c8eb;
+ --nldesign-color-info-rgb: 216, 200, 235;
+ --nldesign-component-navigation-active-background-color: #d94d7f;
+ --nldesign-component-navigation-active-color: #ec86ab;
+}
+
+/* The logo on the login card. The NL Design sheet draws it in a 40 by 32
+ * pixel box, which suits an emblem; this logo is a wordmark,
+ * 3.97 times as wide as it is high. It gets 200 by 44 pixels,
+ * centred in the 100px the card keeps free above the form (the box is
+ * `contain`, so the wordmark keeps its proportions inside it). Same
+ * selectors as the rule it follows (css/systems/nldesign/theme.css). */
+#body-login .guest-box.login-box::after,
+#body-login div.guest-box::after,
+.guest-box.login-box::after,
+div.guest-box.login-box::after {
+ top: 28px !important;
+ width: 200px !important;
+ height: 44px !important;
+}
diff --git a/css/token-overrides/vaartveld.css b/css/token-overrides/vaartveld.css
new file mode 100644
index 000000000..6fcf381e3
--- /dev/null
+++ b/css/token-overrides/vaartveld.css
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: EUPL-1.2
+ SPDX-FileCopyrightText: 2026 Conduction B.V.
+
+ Vaartveld College overrides: the dark page, the dark workspace and the
+ login logo, as css/token-overrides/zuiddrecht.css sets them for zuiddrecht
+ and for the same reasons (openspec/changes/school-token-sets).
+
+ 1. THE PAGE BACKGROUND. Nextcloud keeps the theming background (#F5F6F8)
+ in the dark, so a dark workplace would sit in a light grey frame. In the
+ dark the page takes the colour of the workspace.
+
+ 2. THE WORKSPACE. The generator turns the light #F5F6F8 into a grey that is
+ lighter than Nextcloud's dark cards (#171717), so the cards would sink
+ into it. In the dark the workspace is #121315, below the cards.
+
+ 3. WHAT THE GENERATOR DERIVES BELOW AA. Measured by
+ tests/vitest/schoolTokenSets.spec.js; each is set by hand here:
+ - --nldesign-color-info: the generator kept the info colour at #2f5bd7, 3.07:1 on the dark cards; it takes the dark link colour, as info equals the link in the light
+ - --nldesign-color-info-rgb: the same colour as channels
+
+ This lives outside `css/tokens/` because a shipped token file is one flat
+ `:root { }` block with no at-rule (TokenCssShapeTest). The selectors start
+ with `:root` so they outrank the generated dark file, which loads after
+ this one. */
+@media (prefers-color-scheme: dark) {
+ :root
+ body:not([data-theme-light]):not([data-theme-dark]):not(
+ [data-theme-light-highcontrast]
+ ):not([data-theme-dark-highcontrast]) {
+ --color-background-plain: #121315;
+ --color-background-plain-text: var(--color-main-text);
+ --nldesign-component-content-surface-background-color: #121315;
+ --nldesign-color-info: #9aafec;
+ --nldesign-color-info-rgb: 154, 175, 236;
+ }
+}
+
+:root body[data-theme-dark],
+:root body[data-themes*='dark'] {
+ --color-background-plain: #121315;
+ --color-background-plain-text: var(--color-main-text);
+ --nldesign-component-content-surface-background-color: #121315;
+ --nldesign-color-info: #9aafec;
+ --nldesign-color-info-rgb: 154, 175, 236;
+}
+
+/* The logo on the login card. The NL Design sheet draws it in a 40 by 32
+ * pixel box, which suits an emblem; this logo is a wordmark,
+ * 3.47 times as wide as it is high. It gets 200 by 44 pixels,
+ * centred in the 100px the card keeps free above the form (the box is
+ * `contain`, so the wordmark keeps its proportions inside it). Same
+ * selectors as the rule it follows (css/systems/nldesign/theme.css). */
+#body-login .guest-box.login-box::after,
+#body-login div.guest-box::after,
+.guest-box.login-box::after,
+div.guest-box.login-box::after {
+ top: 28px !important;
+ width: 200px !important;
+ height: 44px !important;
+}
+
+/* The solid selected entry: ink on the accent.
+
+ Where Nextcloud still fills the selected navigation entry solid (the
+ server-rendered navigation of the settings pages, an entry marked
+ --legacy, and every entry on Nextcloud 32 and 33), it fills it with the
+ accent #1FB5A8 and writes the primary's label colour on it: white, which
+ is under 3:1 on this accent. The design writes ink on the accent, so the
+ label colour is ink for those entries only. The wash Nextcloud 34 and later
+ draw keeps its own label (--nldesign-component-navigation-active-color).
+ Same selectors as the rule in css/systems/nldesign/element-overrides.css
+ that hands those entries the label colour, one `:root` in front. */
+:root #app-navigation li.active,
+:root #app-navigation .app-navigation-entry--legacy.active,
+:root #app-navigation-vue .app-navigation-entry--legacy.active,
+:root .app-navigation .app-navigation-entry--legacy.active {
+ --color-primary-element-text: #1a1a1a;
+}
diff --git a/css/token-overrides/warmtepompacademie.css b/css/token-overrides/warmtepompacademie.css
new file mode 100644
index 000000000..06def85a3
--- /dev/null
+++ b/css/token-overrides/warmtepompacademie.css
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: EUPL-1.2
+ SPDX-FileCopyrightText: 2026 Conduction B.V.
+
+ Warmtepompacademie overrides: the dark page, the dark workspace and the
+ login logo, as css/token-overrides/zuiddrecht.css sets them for zuiddrecht
+ and for the same reasons (openspec/changes/school-token-sets).
+
+ 1. THE PAGE BACKGROUND. Nextcloud keeps the theming background (#F5F6F8)
+ in the dark, so a dark workplace would sit in a light grey frame. In the
+ dark the page takes the colour of the workspace.
+
+ 2. THE WORKSPACE. The generator turns the light #F5F6F8 into a grey that is
+ lighter than Nextcloud's dark cards (#171717), so the cards would sink
+ into it. In the dark the workspace is #121315, below the cards.
+
+ This lives outside `css/tokens/` because a shipped token file is one flat
+ `:root { }` block with no at-rule (TokenCssShapeTest). The selectors start
+ with `:root` so they outrank the generated dark file, which loads after
+ this one. */
+@media (prefers-color-scheme: dark) {
+ :root
+ body:not([data-theme-light]):not([data-theme-dark]):not(
+ [data-theme-light-highcontrast]
+ ):not([data-theme-dark-highcontrast]) {
+ --color-background-plain: #121315;
+ --color-background-plain-text: var(--color-main-text);
+ --nldesign-component-content-surface-background-color: #121315;
+ }
+}
+
+:root body[data-theme-dark],
+:root body[data-themes*='dark'] {
+ --color-background-plain: #121315;
+ --color-background-plain-text: var(--color-main-text);
+ --nldesign-component-content-surface-background-color: #121315;
+}
+
+/* The logo on the login card. The NL Design sheet draws it in a 40 by 32
+ * pixel box, which suits an emblem; this logo is a wordmark,
+ * 3.78 times as wide as it is high. It gets 200 by 44 pixels,
+ * centred in the 100px the card keeps free above the form (the box is
+ * `contain`, so the wordmark keeps its proportions inside it). Same
+ * selectors as the rule it follows (css/systems/nldesign/theme.css). */
+#body-login .guest-box.login-box::after,
+#body-login div.guest-box::after,
+.guest-box.login-box::after,
+div.guest-box.login-box::after {
+ top: 28px !important;
+ width: 200px !important;
+ height: 44px !important;
+}
diff --git a/css/token-overrides/wilgenboom.css b/css/token-overrides/wilgenboom.css
new file mode 100644
index 000000000..0dc83353d
--- /dev/null
+++ b/css/token-overrides/wilgenboom.css
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: EUPL-1.2
+ SPDX-FileCopyrightText: 2026 Conduction B.V.
+
+ Basisschool De Wilgenboom overrides: the dark page, the dark workspace and the
+ login logo, as css/token-overrides/zuiddrecht.css sets them for zuiddrecht
+ and for the same reasons (openspec/changes/school-token-sets).
+
+ 1. THE PAGE BACKGROUND. Nextcloud keeps the theming background (#F5F6F8)
+ in the dark, so a dark workplace would sit in a light grey frame. In the
+ dark the page takes the colour of the workspace.
+
+ 2. THE WORKSPACE. The generator turns the light #F5F6F8 into a grey that is
+ lighter than Nextcloud's dark cards (#171717), so the cards would sink
+ into it. In the dark the workspace is #121315, below the cards.
+
+ This lives outside `css/tokens/` because a shipped token file is one flat
+ `:root { }` block with no at-rule (TokenCssShapeTest). The selectors start
+ with `:root` so they outrank the generated dark file, which loads after
+ this one. */
+@media (prefers-color-scheme: dark) {
+ :root
+ body:not([data-theme-light]):not([data-theme-dark]):not(
+ [data-theme-light-highcontrast]
+ ):not([data-theme-dark-highcontrast]) {
+ --color-background-plain: #121315;
+ --color-background-plain-text: var(--color-main-text);
+ --nldesign-component-content-surface-background-color: #121315;
+ }
+}
+
+:root body[data-theme-dark],
+:root body[data-themes*='dark'] {
+ --color-background-plain: #121315;
+ --color-background-plain-text: var(--color-main-text);
+ --nldesign-component-content-surface-background-color: #121315;
+}
+
+/* The logo on the login card. The NL Design sheet draws it in a 40 by 32
+ * pixel box, which suits an emblem; this logo is a wordmark,
+ * 4.77 times as wide as it is high. It gets 200 by 44 pixels,
+ * centred in the 100px the card keeps free above the form (the box is
+ * `contain`, so the wordmark keeps its proportions inside it). Same
+ * selectors as the rule it follows (css/systems/nldesign/theme.css). */
+#body-login .guest-box.login-box::after,
+#body-login div.guest-box::after,
+.guest-box.login-box::after,
+div.guest-box.login-box::after {
+ top: 28px !important;
+ width: 200px !important;
+ height: 44px !important;
+}
+
+/* The solid selected entry: ink on the accent.
+
+ Where Nextcloud still fills the selected navigation entry solid (the
+ server-rendered navigation of the settings pages, an entry marked
+ --legacy, and every entry on Nextcloud 32 and 33), it fills it with the
+ accent #F5B82E and writes the primary's label colour on it: white, which
+ is under 3:1 on this accent. The design writes ink on the accent, so the
+ label colour is ink for those entries only. The wash Nextcloud 34 and later
+ draw keeps its own label (--nldesign-component-navigation-active-color).
+ Same selectors as the rule in css/systems/nldesign/element-overrides.css
+ that hands those entries the label colour, one `:root` in front. */
+:root #app-navigation li.active,
+:root #app-navigation .app-navigation-entry--legacy.active,
+:root #app-navigation-vue .app-navigation-entry--legacy.active,
+:root .app-navigation .app-navigation-entry--legacy.active {
+ --color-primary-element-text: #1a1a1a;
+}
diff --git a/css/tokens/dark/esdoornveen.css b/css/tokens/dark/esdoornveen.css
new file mode 100644
index 000000000..5f97df43e
--- /dev/null
+++ b/css/tokens/dark/esdoornveen.css
@@ -0,0 +1,244 @@
+/* GENERATED by nldesign DarkPaletteService v9 from tokens/esdoornveen.css (sha256:8ac6ac2d78efe283e417e7c6531c3136a3de845af542852764920f4598fa574a) — do not edit */
+@media (prefers-color-scheme: dark) {
+ body:not([data-theme-light]):not([data-theme-dark]):not([data-theme-light-highcontrast]):not([data-theme-dark-highcontrast]) {
+ --esdoornveen-color-accent: #d14274;
+ --esdoornveen-color-accent-light: #330c1b;
+ --esdoornveen-color-accent-text: #e36390;
+ --esdoornveen-color-ink: #d2d3d4;
+ --esdoornveen-color-line: #24272d;
+ --esdoornveen-color-main: #966bc9;
+ --esdoornveen-color-main-deep: #ab87d7;
+ --esdoornveen-color-main-light: #20132e;
+ --esdoornveen-color-muted: #93969c;
+ --esdoornveen-color-surface: #171a20;
+ --nldesign-brand-stripe-color-1: #966bc9;
+ --nldesign-brand-stripe-color-2: #d14274;
+ --nldesign-brand-stripe-color-3: #966bc9;
+ --nldesign-color-background: #171a20;
+ --nldesign-color-background-dark: #1d2026;
+ --nldesign-color-background-darker: #2d333c;
+ --nldesign-color-background-hover: #1d1f23;
+ --nldesign-color-border: #24272d;
+ --nldesign-color-border-dark: #656c78;
+ --nldesign-color-button-primary-background: #966bc9;
+ --nldesign-color-button-primary-border: #966bc9;
+ --nldesign-color-button-primary-hover: #ab87d7;
+ --nldesign-color-button-primary-text: #111111;
+ --nldesign-color-error: #f54949;
+ --nldesign-color-error-hover: #f65656;
+ --nldesign-color-error-rgb: 245, 73, 73;
+ --nldesign-color-favorite: #f48c25;
+ --nldesign-color-focus: #966bc980;
+ --nldesign-color-focus-rgb: 150, 107, 201;
+ --nldesign-color-header-background: #141414;
+ --nldesign-color-header-text: #e2e3e4;
+ --nldesign-color-info: #966bc9;
+ --nldesign-color-info-rgb: 150, 107, 201;
+ --nldesign-color-link: #d8c8eb;
+ --nldesign-color-link-hover: #ab87d7;
+ --nldesign-color-link-visited: #c392e3;
+ --nldesign-color-nav-background: #141414;
+ --nldesign-color-placeholder-dark: #3f3f3f;
+ --nldesign-color-placeholder-light: #2a2a2a;
+ --nldesign-color-primary: #decff0;
+ --nldesign-color-primary-hover: #43206e;
+ --nldesign-color-primary-light: #20132e;
+ --nldesign-color-primary-light-hover: #281b37;
+ --nldesign-color-primary-text: #111111;
+ --nldesign-color-success: #8ad896;
+ --nldesign-color-success-rgb: 138, 216, 150;
+ --nldesign-color-text: #e2e3e4;
+ --nldesign-color-text-light: #9e9e9e;
+ --nldesign-color-text-muted: #999ca3;
+ --nldesign-color-warning: #f8ca77;
+ --nldesign-color-warning-rgb: 248, 202, 119;
+ --nldesign-component-badge-background-color: #966bc9;
+ --nldesign-component-badge-color: #111111;
+ --nldesign-component-button-active-background-color: #281b37;
+ --nldesign-component-button-active-color: #9b6ed1;
+ --nldesign-component-button-border-color: #966bc9;
+ --nldesign-component-button-color: #9b6ed1;
+ --nldesign-component-button-disabled-background-color: #2a2a2a;
+ --nldesign-component-button-disabled-border-color: #535353;
+ --nldesign-component-button-disabled-color: #9e9e9e;
+ --nldesign-component-button-error-color: #000000;
+ --nldesign-component-button-focus-border-color: #966bc980;
+ --nldesign-component-button-hover-background-color: #20132e;
+ --nldesign-component-button-hover-border-color: #ab87d7;
+ --nldesign-component-button-hover-color: #9b6ed1;
+ --nldesign-component-button-primary-action-background-color: #966bc9;
+ --nldesign-component-button-primary-action-border-color: #966bc9;
+ --nldesign-component-button-primary-action-color: #111111;
+ --nldesign-component-button-primary-action-hover-background-color: #ab87d7;
+ --nldesign-component-button-primary-action-hover-color: #2e2e2e;
+ --nldesign-component-button-secondary-action-border-color: #966bc9;
+ --nldesign-component-button-secondary-action-color: #9b6ed1;
+ --nldesign-component-button-secondary-action-hover-background-color: #20132e;
+ --nldesign-component-content-card-shadow-color: #d2d3d40a;
+ --nldesign-component-content-surface-background-color: #171a20;
+ --nldesign-component-form-field-label-color: #e2e3e4;
+ --nldesign-component-form-fieldset-border-color: #24272d;
+ --nldesign-component-form-select-border-color: #24272d;
+ --nldesign-component-form-select-focus-border-color: #966bc9;
+ --nldesign-component-heading-1-color: #e2e3e4;
+ --nldesign-component-heading-2-color: #e2e3e4;
+ --nldesign-component-heading-3-color: #e2e3e4;
+ --nldesign-component-heading-4-color: #e2e3e4;
+ --nldesign-component-heading-5-color: #e2e3e4;
+ --nldesign-component-heading-6-color: #e2e3e4;
+ --nldesign-component-heading-color: #e2e3e4;
+ --nldesign-component-link-color: #9b6ed1;
+ --nldesign-component-link-hover-color: #b491df;
+ --nldesign-component-link-visited-color: #cea0eb;
+ --nldesign-component-navigation-active-background-color: #d14274;
+ --nldesign-component-navigation-active-color: #e36390;
+ --nldesign-component-navigation-badge-background-color: #d14274;
+ --nldesign-component-navigation-badge-color: #000000;
+ --nldesign-component-ordered-list-color: #e2e3e4;
+ --nldesign-component-paragraph-color: #e2e3e4;
+ --nldesign-component-separator-border-color: #24272d;
+ --nldesign-component-status-badge-error-background-color: #310d0a;
+ --nldesign-component-status-badge-error-color: #ff5c5c;
+ --nldesign-component-status-badge-info-background-color: #20132e;
+ --nldesign-component-status-badge-info-color: #b491df;
+ --nldesign-component-status-badge-success-background-color: #192e1e;
+ --nldesign-component-status-badge-success-color: #94e1a0;
+ --nldesign-component-status-badge-warning-background-color: #412d03;
+ --nldesign-component-status-badge-warning-color: #ffd485;
+ --nldesign-component-table-border-color: #24272d;
+ --nldesign-component-table-header-background-color: #1d2026;
+ --nldesign-component-table-header-color: #e2e3e4;
+ --nldesign-component-table-row-hover-background-color: #1d1f23;
+ --nldesign-component-textbox-background-color: #141414;
+ --nldesign-component-textbox-border-color: #5d6474;
+ --nldesign-component-textbox-color: #e2e3e4;
+ --nldesign-component-textbox-disabled-background-color: #2a2a2a;
+ --nldesign-component-textbox-disabled-color: #9e9e9e;
+ --nldesign-component-textbox-focus-border-color: #966bc9;
+ --nldesign-component-textbox-hover-border-color: #656c78;
+ --nldesign-component-textbox-invalid-border-color: #f54949;
+ --nldesign-component-unordered-list-color: #e2e3e4;
+ --nldesign-logo-url: url('../../../img/logos/esdoornveen-dark.svg');
+ }
+}
+body[data-theme-dark],
+body[data-themes*=dark] {
+ --esdoornveen-color-accent: #d14274;
+ --esdoornveen-color-accent-light: #330c1b;
+ --esdoornveen-color-accent-text: #e36390;
+ --esdoornveen-color-ink: #d2d3d4;
+ --esdoornveen-color-line: #24272d;
+ --esdoornveen-color-main: #966bc9;
+ --esdoornveen-color-main-deep: #ab87d7;
+ --esdoornveen-color-main-light: #20132e;
+ --esdoornveen-color-muted: #93969c;
+ --esdoornveen-color-surface: #171a20;
+ --nldesign-brand-stripe-color-1: #966bc9;
+ --nldesign-brand-stripe-color-2: #d14274;
+ --nldesign-brand-stripe-color-3: #966bc9;
+ --nldesign-color-background: #171a20;
+ --nldesign-color-background-dark: #1d2026;
+ --nldesign-color-background-darker: #2d333c;
+ --nldesign-color-background-hover: #1d1f23;
+ --nldesign-color-border: #24272d;
+ --nldesign-color-border-dark: #656c78;
+ --nldesign-color-button-primary-background: #966bc9;
+ --nldesign-color-button-primary-border: #966bc9;
+ --nldesign-color-button-primary-hover: #ab87d7;
+ --nldesign-color-button-primary-text: #111111;
+ --nldesign-color-error: #f54949;
+ --nldesign-color-error-hover: #f65656;
+ --nldesign-color-error-rgb: 245, 73, 73;
+ --nldesign-color-favorite: #f48c25;
+ --nldesign-color-focus: #966bc980;
+ --nldesign-color-focus-rgb: 150, 107, 201;
+ --nldesign-color-header-background: #141414;
+ --nldesign-color-header-text: #e2e3e4;
+ --nldesign-color-info: #966bc9;
+ --nldesign-color-info-rgb: 150, 107, 201;
+ --nldesign-color-link: #d8c8eb;
+ --nldesign-color-link-hover: #ab87d7;
+ --nldesign-color-link-visited: #c392e3;
+ --nldesign-color-nav-background: #141414;
+ --nldesign-color-placeholder-dark: #3f3f3f;
+ --nldesign-color-placeholder-light: #2a2a2a;
+ --nldesign-color-primary: #decff0;
+ --nldesign-color-primary-hover: #43206e;
+ --nldesign-color-primary-light: #20132e;
+ --nldesign-color-primary-light-hover: #281b37;
+ --nldesign-color-primary-text: #111111;
+ --nldesign-color-success: #8ad896;
+ --nldesign-color-success-rgb: 138, 216, 150;
+ --nldesign-color-text: #e2e3e4;
+ --nldesign-color-text-light: #9e9e9e;
+ --nldesign-color-text-muted: #999ca3;
+ --nldesign-color-warning: #f8ca77;
+ --nldesign-color-warning-rgb: 248, 202, 119;
+ --nldesign-component-badge-background-color: #966bc9;
+ --nldesign-component-badge-color: #111111;
+ --nldesign-component-button-active-background-color: #281b37;
+ --nldesign-component-button-active-color: #9b6ed1;
+ --nldesign-component-button-border-color: #966bc9;
+ --nldesign-component-button-color: #9b6ed1;
+ --nldesign-component-button-disabled-background-color: #2a2a2a;
+ --nldesign-component-button-disabled-border-color: #535353;
+ --nldesign-component-button-disabled-color: #9e9e9e;
+ --nldesign-component-button-error-color: #000000;
+ --nldesign-component-button-focus-border-color: #966bc980;
+ --nldesign-component-button-hover-background-color: #20132e;
+ --nldesign-component-button-hover-border-color: #ab87d7;
+ --nldesign-component-button-hover-color: #9b6ed1;
+ --nldesign-component-button-primary-action-background-color: #966bc9;
+ --nldesign-component-button-primary-action-border-color: #966bc9;
+ --nldesign-component-button-primary-action-color: #111111;
+ --nldesign-component-button-primary-action-hover-background-color: #ab87d7;
+ --nldesign-component-button-primary-action-hover-color: #2e2e2e;
+ --nldesign-component-button-secondary-action-border-color: #966bc9;
+ --nldesign-component-button-secondary-action-color: #9b6ed1;
+ --nldesign-component-button-secondary-action-hover-background-color: #20132e;
+ --nldesign-component-content-card-shadow-color: #d2d3d40a;
+ --nldesign-component-content-surface-background-color: #171a20;
+ --nldesign-component-form-field-label-color: #e2e3e4;
+ --nldesign-component-form-fieldset-border-color: #24272d;
+ --nldesign-component-form-select-border-color: #24272d;
+ --nldesign-component-form-select-focus-border-color: #966bc9;
+ --nldesign-component-heading-1-color: #e2e3e4;
+ --nldesign-component-heading-2-color: #e2e3e4;
+ --nldesign-component-heading-3-color: #e2e3e4;
+ --nldesign-component-heading-4-color: #e2e3e4;
+ --nldesign-component-heading-5-color: #e2e3e4;
+ --nldesign-component-heading-6-color: #e2e3e4;
+ --nldesign-component-heading-color: #e2e3e4;
+ --nldesign-component-link-color: #9b6ed1;
+ --nldesign-component-link-hover-color: #b491df;
+ --nldesign-component-link-visited-color: #cea0eb;
+ --nldesign-component-navigation-active-background-color: #d14274;
+ --nldesign-component-navigation-active-color: #e36390;
+ --nldesign-component-navigation-badge-background-color: #d14274;
+ --nldesign-component-navigation-badge-color: #000000;
+ --nldesign-component-ordered-list-color: #e2e3e4;
+ --nldesign-component-paragraph-color: #e2e3e4;
+ --nldesign-component-separator-border-color: #24272d;
+ --nldesign-component-status-badge-error-background-color: #310d0a;
+ --nldesign-component-status-badge-error-color: #ff5c5c;
+ --nldesign-component-status-badge-info-background-color: #20132e;
+ --nldesign-component-status-badge-info-color: #b491df;
+ --nldesign-component-status-badge-success-background-color: #192e1e;
+ --nldesign-component-status-badge-success-color: #94e1a0;
+ --nldesign-component-status-badge-warning-background-color: #412d03;
+ --nldesign-component-status-badge-warning-color: #ffd485;
+ --nldesign-component-table-border-color: #24272d;
+ --nldesign-component-table-header-background-color: #1d2026;
+ --nldesign-component-table-header-color: #e2e3e4;
+ --nldesign-component-table-row-hover-background-color: #1d1f23;
+ --nldesign-component-textbox-background-color: #141414;
+ --nldesign-component-textbox-border-color: #5d6474;
+ --nldesign-component-textbox-color: #e2e3e4;
+ --nldesign-component-textbox-disabled-background-color: #2a2a2a;
+ --nldesign-component-textbox-disabled-color: #9e9e9e;
+ --nldesign-component-textbox-focus-border-color: #966bc9;
+ --nldesign-component-textbox-hover-border-color: #656c78;
+ --nldesign-component-textbox-invalid-border-color: #f54949;
+ --nldesign-component-unordered-list-color: #e2e3e4;
+ --nldesign-logo-url: url('../../../img/logos/esdoornveen-dark.svg');
+}
diff --git a/css/tokens/dark/vaartveld.css b/css/tokens/dark/vaartveld.css
new file mode 100644
index 000000000..ab58ad4ac
--- /dev/null
+++ b/css/tokens/dark/vaartveld.css
@@ -0,0 +1,244 @@
+/* GENERATED by nldesign DarkPaletteService v9 from tokens/vaartveld.css (sha256:68520f56278546eecb05e89457f957288f0a301f063c8da11170b9f315d13534) — do not edit */
+@media (prefers-color-scheme: dark) {
+ body:not([data-theme-light]):not([data-theme-dark]):not([data-theme-light-highcontrast]):not([data-theme-dark-highcontrast]) {
+ --nldesign-brand-stripe-color-1: #2f5bd7;
+ --nldesign-brand-stripe-color-2: #4cd7cb;
+ --nldesign-brand-stripe-color-3: #2f5bd7;
+ --nldesign-color-background: #171a20;
+ --nldesign-color-background-dark: #1d2026;
+ --nldesign-color-background-darker: #2d333c;
+ --nldesign-color-background-hover: #1d1f23;
+ --nldesign-color-border: #24272d;
+ --nldesign-color-border-dark: #656c78;
+ --nldesign-color-button-primary-background: #2f5bd7;
+ --nldesign-color-button-primary-border: #2f5bd7;
+ --nldesign-color-button-primary-hover: #6a88e2;
+ --nldesign-color-button-primary-text: #fefefe;
+ --nldesign-color-error: #f54949;
+ --nldesign-color-error-hover: #f65656;
+ --nldesign-color-error-rgb: 245, 73, 73;
+ --nldesign-color-favorite: #f48c25;
+ --nldesign-color-focus: #2f5bd780;
+ --nldesign-color-focus-rgb: 47, 91, 215;
+ --nldesign-color-header-background: #141414;
+ --nldesign-color-header-text: #e2e3e4;
+ --nldesign-color-info: #2f5bd7;
+ --nldesign-color-info-rgb: 47, 91, 215;
+ --nldesign-color-link: #9aafec;
+ --nldesign-color-link-hover: #6a88e2;
+ --nldesign-color-link-visited: #c392e3;
+ --nldesign-color-nav-background: #141414;
+ --nldesign-color-placeholder-dark: #3f3f3f;
+ --nldesign-color-placeholder-light: #2a2a2a;
+ --nldesign-color-primary: #89a3ee;
+ --nldesign-color-primary-hover: #14338f;
+ --nldesign-color-primary-light: #0a1735;
+ --nldesign-color-primary-light-hover: #0e1c3f;
+ --nldesign-color-primary-text: #111111;
+ --nldesign-color-success: #8ad896;
+ --nldesign-color-success-rgb: 138, 216, 150;
+ --nldesign-color-text: #e2e3e4;
+ --nldesign-color-text-light: #9e9e9e;
+ --nldesign-color-text-muted: #999ca3;
+ --nldesign-color-warning: #f8ca77;
+ --nldesign-color-warning-rgb: 248, 202, 119;
+ --nldesign-component-badge-background-color: #2f5bd7;
+ --nldesign-component-badge-color: #fefefe;
+ --nldesign-component-button-active-background-color: #0e1c3f;
+ --nldesign-component-button-active-color: #567be7;
+ --nldesign-component-button-border-color: #2f5bd7;
+ --nldesign-component-button-color: #567be7;
+ --nldesign-component-button-disabled-background-color: #2a2a2a;
+ --nldesign-component-button-disabled-border-color: #535353;
+ --nldesign-component-button-disabled-color: #9e9e9e;
+ --nldesign-component-button-error-color: #000000;
+ --nldesign-component-button-focus-border-color: #2f5bd780;
+ --nldesign-component-button-hover-background-color: #0a1735;
+ --nldesign-component-button-hover-border-color: #6a88e2;
+ --nldesign-component-button-hover-color: #567be7;
+ --nldesign-component-button-primary-action-background-color: #2f5bd7;
+ --nldesign-component-button-primary-action-border-color: #2f5bd7;
+ --nldesign-component-button-primary-action-color: #fefefe;
+ --nldesign-component-button-primary-action-hover-background-color: #6a88e2;
+ --nldesign-component-button-primary-action-hover-color: #222222;
+ --nldesign-component-button-secondary-action-border-color: #2f5bd7;
+ --nldesign-component-button-secondary-action-color: #c6d2f7;
+ --nldesign-component-button-secondary-action-hover-background-color: #0a1735;
+ --nldesign-component-content-card-shadow-color: #d2d3d40a;
+ --nldesign-component-content-surface-background-color: #171a20;
+ --nldesign-component-form-field-label-color: #e2e3e4;
+ --nldesign-component-form-fieldset-border-color: #24272d;
+ --nldesign-component-form-select-border-color: #24272d;
+ --nldesign-component-form-select-focus-border-color: #2f5bd7;
+ --nldesign-component-heading-1-color: #e2e3e4;
+ --nldesign-component-heading-2-color: #e2e3e4;
+ --nldesign-component-heading-3-color: #e2e3e4;
+ --nldesign-component-heading-4-color: #e2e3e4;
+ --nldesign-component-heading-5-color: #e2e3e4;
+ --nldesign-component-heading-6-color: #e2e3e4;
+ --nldesign-component-heading-color: #e2e3e4;
+ --nldesign-component-link-color: #c6d2f7;
+ --nldesign-component-link-hover-color: #708feb;
+ --nldesign-component-link-visited-color: #cea0eb;
+ --nldesign-component-navigation-active-background-color: #4cd7cb;
+ --nldesign-component-navigation-active-color: #9df4eb;
+ --nldesign-component-navigation-badge-background-color: #4cd7cb;
+ --nldesign-component-navigation-badge-color: #111111;
+ --nldesign-component-ordered-list-color: #e2e3e4;
+ --nldesign-component-paragraph-color: #e2e3e4;
+ --nldesign-component-separator-border-color: #24272d;
+ --nldesign-component-status-badge-error-background-color: #310d0a;
+ --nldesign-component-status-badge-error-color: #ff5c5c;
+ --nldesign-component-status-badge-info-background-color: #0a1735;
+ --nldesign-component-status-badge-info-color: #708feb;
+ --nldesign-component-status-badge-success-background-color: #192e1e;
+ --nldesign-component-status-badge-success-color: #94e1a0;
+ --nldesign-component-status-badge-warning-background-color: #412d03;
+ --nldesign-component-status-badge-warning-color: #ffd485;
+ --nldesign-component-table-border-color: #24272d;
+ --nldesign-component-table-header-background-color: #1d2026;
+ --nldesign-component-table-header-color: #e2e3e4;
+ --nldesign-component-table-row-hover-background-color: #1d1f23;
+ --nldesign-component-textbox-background-color: #141414;
+ --nldesign-component-textbox-border-color: #5d6474;
+ --nldesign-component-textbox-color: #e2e3e4;
+ --nldesign-component-textbox-disabled-background-color: #2a2a2a;
+ --nldesign-component-textbox-disabled-color: #9e9e9e;
+ --nldesign-component-textbox-focus-border-color: #2f5bd7;
+ --nldesign-component-textbox-hover-border-color: #656c78;
+ --nldesign-component-textbox-invalid-border-color: #f54949;
+ --nldesign-component-unordered-list-color: #e2e3e4;
+ --nldesign-logo-url: url('../../../img/logos/vaartveld-dark.svg');
+ --vaartveld-color-accent: #4cd7cb;
+ --vaartveld-color-accent-light: #143a35;
+ --vaartveld-color-accent-text: #9df4eb;
+ --vaartveld-color-ink: #d2d3d4;
+ --vaartveld-color-line: #24272d;
+ --vaartveld-color-main: #2f5bd7;
+ --vaartveld-color-main-deep: #6a88e2;
+ --vaartveld-color-main-light: #0a1735;
+ --vaartveld-color-muted: #93969c;
+ --vaartveld-color-surface: #171a20;
+ }
+}
+body[data-theme-dark],
+body[data-themes*=dark] {
+ --nldesign-brand-stripe-color-1: #2f5bd7;
+ --nldesign-brand-stripe-color-2: #4cd7cb;
+ --nldesign-brand-stripe-color-3: #2f5bd7;
+ --nldesign-color-background: #171a20;
+ --nldesign-color-background-dark: #1d2026;
+ --nldesign-color-background-darker: #2d333c;
+ --nldesign-color-background-hover: #1d1f23;
+ --nldesign-color-border: #24272d;
+ --nldesign-color-border-dark: #656c78;
+ --nldesign-color-button-primary-background: #2f5bd7;
+ --nldesign-color-button-primary-border: #2f5bd7;
+ --nldesign-color-button-primary-hover: #6a88e2;
+ --nldesign-color-button-primary-text: #fefefe;
+ --nldesign-color-error: #f54949;
+ --nldesign-color-error-hover: #f65656;
+ --nldesign-color-error-rgb: 245, 73, 73;
+ --nldesign-color-favorite: #f48c25;
+ --nldesign-color-focus: #2f5bd780;
+ --nldesign-color-focus-rgb: 47, 91, 215;
+ --nldesign-color-header-background: #141414;
+ --nldesign-color-header-text: #e2e3e4;
+ --nldesign-color-info: #2f5bd7;
+ --nldesign-color-info-rgb: 47, 91, 215;
+ --nldesign-color-link: #9aafec;
+ --nldesign-color-link-hover: #6a88e2;
+ --nldesign-color-link-visited: #c392e3;
+ --nldesign-color-nav-background: #141414;
+ --nldesign-color-placeholder-dark: #3f3f3f;
+ --nldesign-color-placeholder-light: #2a2a2a;
+ --nldesign-color-primary: #89a3ee;
+ --nldesign-color-primary-hover: #14338f;
+ --nldesign-color-primary-light: #0a1735;
+ --nldesign-color-primary-light-hover: #0e1c3f;
+ --nldesign-color-primary-text: #111111;
+ --nldesign-color-success: #8ad896;
+ --nldesign-color-success-rgb: 138, 216, 150;
+ --nldesign-color-text: #e2e3e4;
+ --nldesign-color-text-light: #9e9e9e;
+ --nldesign-color-text-muted: #999ca3;
+ --nldesign-color-warning: #f8ca77;
+ --nldesign-color-warning-rgb: 248, 202, 119;
+ --nldesign-component-badge-background-color: #2f5bd7;
+ --nldesign-component-badge-color: #fefefe;
+ --nldesign-component-button-active-background-color: #0e1c3f;
+ --nldesign-component-button-active-color: #567be7;
+ --nldesign-component-button-border-color: #2f5bd7;
+ --nldesign-component-button-color: #567be7;
+ --nldesign-component-button-disabled-background-color: #2a2a2a;
+ --nldesign-component-button-disabled-border-color: #535353;
+ --nldesign-component-button-disabled-color: #9e9e9e;
+ --nldesign-component-button-error-color: #000000;
+ --nldesign-component-button-focus-border-color: #2f5bd780;
+ --nldesign-component-button-hover-background-color: #0a1735;
+ --nldesign-component-button-hover-border-color: #6a88e2;
+ --nldesign-component-button-hover-color: #567be7;
+ --nldesign-component-button-primary-action-background-color: #2f5bd7;
+ --nldesign-component-button-primary-action-border-color: #2f5bd7;
+ --nldesign-component-button-primary-action-color: #fefefe;
+ --nldesign-component-button-primary-action-hover-background-color: #6a88e2;
+ --nldesign-component-button-primary-action-hover-color: #222222;
+ --nldesign-component-button-secondary-action-border-color: #2f5bd7;
+ --nldesign-component-button-secondary-action-color: #c6d2f7;
+ --nldesign-component-button-secondary-action-hover-background-color: #0a1735;
+ --nldesign-component-content-card-shadow-color: #d2d3d40a;
+ --nldesign-component-content-surface-background-color: #171a20;
+ --nldesign-component-form-field-label-color: #e2e3e4;
+ --nldesign-component-form-fieldset-border-color: #24272d;
+ --nldesign-component-form-select-border-color: #24272d;
+ --nldesign-component-form-select-focus-border-color: #2f5bd7;
+ --nldesign-component-heading-1-color: #e2e3e4;
+ --nldesign-component-heading-2-color: #e2e3e4;
+ --nldesign-component-heading-3-color: #e2e3e4;
+ --nldesign-component-heading-4-color: #e2e3e4;
+ --nldesign-component-heading-5-color: #e2e3e4;
+ --nldesign-component-heading-6-color: #e2e3e4;
+ --nldesign-component-heading-color: #e2e3e4;
+ --nldesign-component-link-color: #c6d2f7;
+ --nldesign-component-link-hover-color: #708feb;
+ --nldesign-component-link-visited-color: #cea0eb;
+ --nldesign-component-navigation-active-background-color: #4cd7cb;
+ --nldesign-component-navigation-active-color: #9df4eb;
+ --nldesign-component-navigation-badge-background-color: #4cd7cb;
+ --nldesign-component-navigation-badge-color: #111111;
+ --nldesign-component-ordered-list-color: #e2e3e4;
+ --nldesign-component-paragraph-color: #e2e3e4;
+ --nldesign-component-separator-border-color: #24272d;
+ --nldesign-component-status-badge-error-background-color: #310d0a;
+ --nldesign-component-status-badge-error-color: #ff5c5c;
+ --nldesign-component-status-badge-info-background-color: #0a1735;
+ --nldesign-component-status-badge-info-color: #708feb;
+ --nldesign-component-status-badge-success-background-color: #192e1e;
+ --nldesign-component-status-badge-success-color: #94e1a0;
+ --nldesign-component-status-badge-warning-background-color: #412d03;
+ --nldesign-component-status-badge-warning-color: #ffd485;
+ --nldesign-component-table-border-color: #24272d;
+ --nldesign-component-table-header-background-color: #1d2026;
+ --nldesign-component-table-header-color: #e2e3e4;
+ --nldesign-component-table-row-hover-background-color: #1d1f23;
+ --nldesign-component-textbox-background-color: #141414;
+ --nldesign-component-textbox-border-color: #5d6474;
+ --nldesign-component-textbox-color: #e2e3e4;
+ --nldesign-component-textbox-disabled-background-color: #2a2a2a;
+ --nldesign-component-textbox-disabled-color: #9e9e9e;
+ --nldesign-component-textbox-focus-border-color: #2f5bd7;
+ --nldesign-component-textbox-hover-border-color: #656c78;
+ --nldesign-component-textbox-invalid-border-color: #f54949;
+ --nldesign-component-unordered-list-color: #e2e3e4;
+ --nldesign-logo-url: url('../../../img/logos/vaartveld-dark.svg');
+ --vaartveld-color-accent: #4cd7cb;
+ --vaartveld-color-accent-light: #143a35;
+ --vaartveld-color-accent-text: #9df4eb;
+ --vaartveld-color-ink: #d2d3d4;
+ --vaartveld-color-line: #24272d;
+ --vaartveld-color-main: #2f5bd7;
+ --vaartveld-color-main-deep: #6a88e2;
+ --vaartveld-color-main-light: #0a1735;
+ --vaartveld-color-muted: #93969c;
+ --vaartveld-color-surface: #171a20;
+}
diff --git a/css/tokens/dark/warmtepompacademie.css b/css/tokens/dark/warmtepompacademie.css
new file mode 100644
index 000000000..71cea3410
--- /dev/null
+++ b/css/tokens/dark/warmtepompacademie.css
@@ -0,0 +1,246 @@
+/* GENERATED by nldesign DarkPaletteService v9 from tokens/warmtepompacademie.css (sha256:b9f1022121447cad03bf560e643d517d99e0d71d4c37fa383adb126207aa0277) — do not edit */
+@media (prefers-color-scheme: dark) {
+ body:not([data-theme-light]):not([data-theme-dark]):not([data-theme-light-highcontrast]):not([data-theme-dark-highcontrast]) {
+ --nldesign-brand-stripe-color-1: #79e0ec;
+ --nldesign-brand-stripe-color-2: #24272d;
+ --nldesign-brand-stripe-color-3: #e6612d;
+ --nldesign-color-background: #171a20;
+ --nldesign-color-background-dark: #1d2026;
+ --nldesign-color-background-darker: #2d333c;
+ --nldesign-color-background-hover: #1d1f23;
+ --nldesign-color-border: #24272d;
+ --nldesign-color-border-dark: #656c78;
+ --nldesign-color-button-primary-background: #79e0ec;
+ --nldesign-color-button-primary-border: #79e0ec;
+ --nldesign-color-button-primary-hover: #95e6f0;
+ --nldesign-color-button-primary-text: #3e3e3e;
+ --nldesign-color-error: #f54949;
+ --nldesign-color-error-hover: #f65656;
+ --nldesign-color-error-rgb: 245, 73, 73;
+ --nldesign-color-favorite: #f48c25;
+ --nldesign-color-focus: #79e0ec80;
+ --nldesign-color-focus-rgb: 121, 224, 236;
+ --nldesign-color-header-background: #141414;
+ --nldesign-color-header-text: #e2e3e4;
+ --nldesign-color-info: #79e0ec;
+ --nldesign-color-info-rgb: 121, 224, 236;
+ --nldesign-color-link: #79e0ec;
+ --nldesign-color-link-hover: #95e6f0;
+ --nldesign-color-link-visited: #c392e3;
+ --nldesign-color-nav-background: #141414;
+ --nldesign-color-placeholder-dark: #3f3f3f;
+ --nldesign-color-placeholder-light: #2a2a2a;
+ --nldesign-color-primary: #1ad4ea;
+ --nldesign-color-primary-hover: #084f58;
+ --nldesign-color-primary-light: #182f33;
+ --nldesign-color-primary-light-hover: #1f3a3e;
+ --nldesign-color-primary-text: #111111;
+ --nldesign-color-success: #8ad896;
+ --nldesign-color-success-rgb: 138, 216, 150;
+ --nldesign-color-text: #e2e3e4;
+ --nldesign-color-text-light: #9e9e9e;
+ --nldesign-color-text-muted: #999ca3;
+ --nldesign-color-warning: #f8ca77;
+ --nldesign-color-warning-rgb: 248, 202, 119;
+ --nldesign-component-badge-background-color: #79e0ec;
+ --nldesign-component-badge-color: #3e3e3e;
+ --nldesign-component-button-active-background-color: #1f3a3e;
+ --nldesign-component-button-active-color: #85e8f4;
+ --nldesign-component-button-border-color: #79e0ec;
+ --nldesign-component-button-color: #85e8f4;
+ --nldesign-component-button-disabled-background-color: #2a2a2a;
+ --nldesign-component-button-disabled-border-color: #535353;
+ --nldesign-component-button-disabled-color: #9e9e9e;
+ --nldesign-component-button-error-color: #000000;
+ --nldesign-component-button-focus-border-color: #79e0ec80;
+ --nldesign-component-button-hover-background-color: #182f33;
+ --nldesign-component-button-hover-border-color: #95e6f0;
+ --nldesign-component-button-hover-color: #85e8f4;
+ --nldesign-component-button-primary-action-background-color: #79e0ec;
+ --nldesign-component-button-primary-action-border-color: #79e0ec;
+ --nldesign-component-button-primary-action-color: #3e3e3e;
+ --nldesign-component-button-primary-action-hover-background-color: #95e6f0;
+ --nldesign-component-button-primary-action-hover-color: #5e5e5e;
+ --nldesign-component-button-secondary-action-border-color: #79e0ec;
+ --nldesign-component-button-secondary-action-color: #85e8f4;
+ --nldesign-component-button-secondary-action-hover-background-color: #182f33;
+ --nldesign-component-content-card-shadow-color: #d2d3d40a;
+ --nldesign-component-content-surface-background-color: #171a20;
+ --nldesign-component-form-field-label-color: #e2e3e4;
+ --nldesign-component-form-fieldset-border-color: #24272d;
+ --nldesign-component-form-select-border-color: #24272d;
+ --nldesign-component-form-select-focus-border-color: #79e0ec;
+ --nldesign-component-heading-1-color: #e2e3e4;
+ --nldesign-component-heading-2-color: #e2e3e4;
+ --nldesign-component-heading-3-color: #e2e3e4;
+ --nldesign-component-heading-4-color: #e2e3e4;
+ --nldesign-component-heading-5-color: #e2e3e4;
+ --nldesign-component-heading-6-color: #e2e3e4;
+ --nldesign-component-heading-color: #e2e3e4;
+ --nldesign-component-link-color: #85e8f4;
+ --nldesign-component-link-hover-color: #a7eef7;
+ --nldesign-component-link-visited-color: #cea0eb;
+ --nldesign-component-navigation-active-background-color: #e9713f;
+ --nldesign-component-navigation-active-color: #ed8765;
+ --nldesign-component-navigation-badge-background-color: #e9713f;
+ --nldesign-component-navigation-badge-color: #111111;
+ --nldesign-component-ordered-list-color: #e2e3e4;
+ --nldesign-component-paragraph-color: #e2e3e4;
+ --nldesign-component-separator-border-color: #24272d;
+ --nldesign-component-status-badge-error-background-color: #310d0a;
+ --nldesign-component-status-badge-error-color: #ff5c5c;
+ --nldesign-component-status-badge-info-background-color: #182f33;
+ --nldesign-component-status-badge-info-color: #a7eef7;
+ --nldesign-component-status-badge-success-background-color: #192e1e;
+ --nldesign-component-status-badge-success-color: #94e1a0;
+ --nldesign-component-status-badge-warning-background-color: #412d03;
+ --nldesign-component-status-badge-warning-color: #ffd485;
+ --nldesign-component-table-border-color: #24272d;
+ --nldesign-component-table-header-background-color: #1d2026;
+ --nldesign-component-table-header-color: #e2e3e4;
+ --nldesign-component-table-row-hover-background-color: #1d1f23;
+ --nldesign-component-textbox-background-color: #141414;
+ --nldesign-component-textbox-border-color: #5d6474;
+ --nldesign-component-textbox-color: #e2e3e4;
+ --nldesign-component-textbox-disabled-background-color: #2a2a2a;
+ --nldesign-component-textbox-disabled-color: #9e9e9e;
+ --nldesign-component-textbox-focus-border-color: #79e0ec;
+ --nldesign-component-textbox-hover-border-color: #656c78;
+ --nldesign-component-textbox-invalid-border-color: #f54949;
+ --nldesign-component-unordered-list-color: #e2e3e4;
+ --nldesign-logo-url: url('../../../img/logos/warmtepompacademie-dark.svg');
+ --warmtepompacademie-color-accent: #e9713f;
+ --warmtepompacademie-color-accent-light: #3f2109;
+ --warmtepompacademie-color-accent-mark: #e6612d;
+ --warmtepompacademie-color-accent-text: #ed8765;
+ --warmtepompacademie-color-ink: #d2d3d4;
+ --warmtepompacademie-color-line: #24272d;
+ --warmtepompacademie-color-main: #79e0ec;
+ --warmtepompacademie-color-main-deep: #95e6f0;
+ --warmtepompacademie-color-main-light: #182f33;
+ --warmtepompacademie-color-muted: #93969c;
+ --warmtepompacademie-color-surface: #171a20;
+ }
+}
+body[data-theme-dark],
+body[data-themes*=dark] {
+ --nldesign-brand-stripe-color-1: #79e0ec;
+ --nldesign-brand-stripe-color-2: #24272d;
+ --nldesign-brand-stripe-color-3: #e6612d;
+ --nldesign-color-background: #171a20;
+ --nldesign-color-background-dark: #1d2026;
+ --nldesign-color-background-darker: #2d333c;
+ --nldesign-color-background-hover: #1d1f23;
+ --nldesign-color-border: #24272d;
+ --nldesign-color-border-dark: #656c78;
+ --nldesign-color-button-primary-background: #79e0ec;
+ --nldesign-color-button-primary-border: #79e0ec;
+ --nldesign-color-button-primary-hover: #95e6f0;
+ --nldesign-color-button-primary-text: #3e3e3e;
+ --nldesign-color-error: #f54949;
+ --nldesign-color-error-hover: #f65656;
+ --nldesign-color-error-rgb: 245, 73, 73;
+ --nldesign-color-favorite: #f48c25;
+ --nldesign-color-focus: #79e0ec80;
+ --nldesign-color-focus-rgb: 121, 224, 236;
+ --nldesign-color-header-background: #141414;
+ --nldesign-color-header-text: #e2e3e4;
+ --nldesign-color-info: #79e0ec;
+ --nldesign-color-info-rgb: 121, 224, 236;
+ --nldesign-color-link: #79e0ec;
+ --nldesign-color-link-hover: #95e6f0;
+ --nldesign-color-link-visited: #c392e3;
+ --nldesign-color-nav-background: #141414;
+ --nldesign-color-placeholder-dark: #3f3f3f;
+ --nldesign-color-placeholder-light: #2a2a2a;
+ --nldesign-color-primary: #1ad4ea;
+ --nldesign-color-primary-hover: #084f58;
+ --nldesign-color-primary-light: #182f33;
+ --nldesign-color-primary-light-hover: #1f3a3e;
+ --nldesign-color-primary-text: #111111;
+ --nldesign-color-success: #8ad896;
+ --nldesign-color-success-rgb: 138, 216, 150;
+ --nldesign-color-text: #e2e3e4;
+ --nldesign-color-text-light: #9e9e9e;
+ --nldesign-color-text-muted: #999ca3;
+ --nldesign-color-warning: #f8ca77;
+ --nldesign-color-warning-rgb: 248, 202, 119;
+ --nldesign-component-badge-background-color: #79e0ec;
+ --nldesign-component-badge-color: #3e3e3e;
+ --nldesign-component-button-active-background-color: #1f3a3e;
+ --nldesign-component-button-active-color: #85e8f4;
+ --nldesign-component-button-border-color: #79e0ec;
+ --nldesign-component-button-color: #85e8f4;
+ --nldesign-component-button-disabled-background-color: #2a2a2a;
+ --nldesign-component-button-disabled-border-color: #535353;
+ --nldesign-component-button-disabled-color: #9e9e9e;
+ --nldesign-component-button-error-color: #000000;
+ --nldesign-component-button-focus-border-color: #79e0ec80;
+ --nldesign-component-button-hover-background-color: #182f33;
+ --nldesign-component-button-hover-border-color: #95e6f0;
+ --nldesign-component-button-hover-color: #85e8f4;
+ --nldesign-component-button-primary-action-background-color: #79e0ec;
+ --nldesign-component-button-primary-action-border-color: #79e0ec;
+ --nldesign-component-button-primary-action-color: #3e3e3e;
+ --nldesign-component-button-primary-action-hover-background-color: #95e6f0;
+ --nldesign-component-button-primary-action-hover-color: #5e5e5e;
+ --nldesign-component-button-secondary-action-border-color: #79e0ec;
+ --nldesign-component-button-secondary-action-color: #85e8f4;
+ --nldesign-component-button-secondary-action-hover-background-color: #182f33;
+ --nldesign-component-content-card-shadow-color: #d2d3d40a;
+ --nldesign-component-content-surface-background-color: #171a20;
+ --nldesign-component-form-field-label-color: #e2e3e4;
+ --nldesign-component-form-fieldset-border-color: #24272d;
+ --nldesign-component-form-select-border-color: #24272d;
+ --nldesign-component-form-select-focus-border-color: #79e0ec;
+ --nldesign-component-heading-1-color: #e2e3e4;
+ --nldesign-component-heading-2-color: #e2e3e4;
+ --nldesign-component-heading-3-color: #e2e3e4;
+ --nldesign-component-heading-4-color: #e2e3e4;
+ --nldesign-component-heading-5-color: #e2e3e4;
+ --nldesign-component-heading-6-color: #e2e3e4;
+ --nldesign-component-heading-color: #e2e3e4;
+ --nldesign-component-link-color: #85e8f4;
+ --nldesign-component-link-hover-color: #a7eef7;
+ --nldesign-component-link-visited-color: #cea0eb;
+ --nldesign-component-navigation-active-background-color: #e9713f;
+ --nldesign-component-navigation-active-color: #ed8765;
+ --nldesign-component-navigation-badge-background-color: #e9713f;
+ --nldesign-component-navigation-badge-color: #111111;
+ --nldesign-component-ordered-list-color: #e2e3e4;
+ --nldesign-component-paragraph-color: #e2e3e4;
+ --nldesign-component-separator-border-color: #24272d;
+ --nldesign-component-status-badge-error-background-color: #310d0a;
+ --nldesign-component-status-badge-error-color: #ff5c5c;
+ --nldesign-component-status-badge-info-background-color: #182f33;
+ --nldesign-component-status-badge-info-color: #a7eef7;
+ --nldesign-component-status-badge-success-background-color: #192e1e;
+ --nldesign-component-status-badge-success-color: #94e1a0;
+ --nldesign-component-status-badge-warning-background-color: #412d03;
+ --nldesign-component-status-badge-warning-color: #ffd485;
+ --nldesign-component-table-border-color: #24272d;
+ --nldesign-component-table-header-background-color: #1d2026;
+ --nldesign-component-table-header-color: #e2e3e4;
+ --nldesign-component-table-row-hover-background-color: #1d1f23;
+ --nldesign-component-textbox-background-color: #141414;
+ --nldesign-component-textbox-border-color: #5d6474;
+ --nldesign-component-textbox-color: #e2e3e4;
+ --nldesign-component-textbox-disabled-background-color: #2a2a2a;
+ --nldesign-component-textbox-disabled-color: #9e9e9e;
+ --nldesign-component-textbox-focus-border-color: #79e0ec;
+ --nldesign-component-textbox-hover-border-color: #656c78;
+ --nldesign-component-textbox-invalid-border-color: #f54949;
+ --nldesign-component-unordered-list-color: #e2e3e4;
+ --nldesign-logo-url: url('../../../img/logos/warmtepompacademie-dark.svg');
+ --warmtepompacademie-color-accent: #e9713f;
+ --warmtepompacademie-color-accent-light: #3f2109;
+ --warmtepompacademie-color-accent-mark: #e6612d;
+ --warmtepompacademie-color-accent-text: #ed8765;
+ --warmtepompacademie-color-ink: #d2d3d4;
+ --warmtepompacademie-color-line: #24272d;
+ --warmtepompacademie-color-main: #79e0ec;
+ --warmtepompacademie-color-main-deep: #95e6f0;
+ --warmtepompacademie-color-main-light: #182f33;
+ --warmtepompacademie-color-muted: #93969c;
+ --warmtepompacademie-color-surface: #171a20;
+}
diff --git a/css/tokens/dark/wilgenboom.css b/css/tokens/dark/wilgenboom.css
new file mode 100644
index 000000000..a39b52620
--- /dev/null
+++ b/css/tokens/dark/wilgenboom.css
@@ -0,0 +1,244 @@
+/* GENERATED by nldesign DarkPaletteService v9 from tokens/wilgenboom.css (sha256:aa4115341e3337618236e3a119a4dec711ae543d9e7c221e34e15245c9d46b33) — do not edit */
+@media (prefers-color-scheme: dark) {
+ body:not([data-theme-light]):not([data-theme-dark]):not([data-theme-light-highcontrast]):not([data-theme-dark-highcontrast]) {
+ --nldesign-brand-stripe-color-1: #8cc8a7;
+ --nldesign-brand-stripe-color-2: #cc9414;
+ --nldesign-brand-stripe-color-3: #8cc8a7;
+ --nldesign-color-background: #171a20;
+ --nldesign-color-background-dark: #1d2026;
+ --nldesign-color-background-darker: #2d333c;
+ --nldesign-color-background-hover: #1d1f23;
+ --nldesign-color-border: #24272d;
+ --nldesign-color-border-dark: #656c78;
+ --nldesign-color-button-primary-background: #8cc8a7;
+ --nldesign-color-button-primary-border: #8cc8a7;
+ --nldesign-color-button-primary-hover: #a7d6bd;
+ --nldesign-color-button-primary-text: #3e3e3e;
+ --nldesign-color-error: #f54949;
+ --nldesign-color-error-hover: #f65656;
+ --nldesign-color-error-rgb: 245, 73, 73;
+ --nldesign-color-favorite: #f48c25;
+ --nldesign-color-focus: #8cc8a780;
+ --nldesign-color-focus-rgb: 140, 200, 167;
+ --nldesign-color-header-background: #141414;
+ --nldesign-color-header-text: #e2e3e4;
+ --nldesign-color-info: #8cc8a7;
+ --nldesign-color-info-rgb: 140, 200, 167;
+ --nldesign-color-link: #8cc8a7;
+ --nldesign-color-link-hover: #a7d6bd;
+ --nldesign-color-link-visited: #c392e3;
+ --nldesign-color-nav-background: #141414;
+ --nldesign-color-placeholder-dark: #3f3f3f;
+ --nldesign-color-placeholder-light: #2a2a2a;
+ --nldesign-color-primary: #60b988;
+ --nldesign-color-primary-hover: #1f4a33;
+ --nldesign-color-primary-light: #1c2c21;
+ --nldesign-color-primary-light-hover: #24362b;
+ --nldesign-color-primary-text: #111111;
+ --nldesign-color-success: #8ad896;
+ --nldesign-color-success-rgb: 138, 216, 150;
+ --nldesign-color-text: #e2e3e4;
+ --nldesign-color-text-light: #9e9e9e;
+ --nldesign-color-text-muted: #999ca3;
+ --nldesign-color-warning: #f8ca77;
+ --nldesign-color-warning-rgb: 248, 202, 119;
+ --nldesign-component-badge-background-color: #8cc8a7;
+ --nldesign-component-badge-color: #3e3e3e;
+ --nldesign-component-button-active-background-color: #24362b;
+ --nldesign-component-button-active-color: #94d0af;
+ --nldesign-component-button-border-color: #8cc8a7;
+ --nldesign-component-button-color: #94d0af;
+ --nldesign-component-button-disabled-background-color: #2a2a2a;
+ --nldesign-component-button-disabled-border-color: #535353;
+ --nldesign-component-button-disabled-color: #9e9e9e;
+ --nldesign-component-button-error-color: #000000;
+ --nldesign-component-button-focus-border-color: #8cc8a780;
+ --nldesign-component-button-hover-background-color: #1c2c21;
+ --nldesign-component-button-hover-border-color: #a7d6bd;
+ --nldesign-component-button-hover-color: #94d0af;
+ --nldesign-component-button-primary-action-background-color: #8cc8a7;
+ --nldesign-component-button-primary-action-border-color: #8cc8a7;
+ --nldesign-component-button-primary-action-color: #3e3e3e;
+ --nldesign-component-button-primary-action-hover-background-color: #a7d6bd;
+ --nldesign-component-button-primary-action-hover-color: #3e3e3e;
+ --nldesign-component-button-secondary-action-border-color: #8cc8a7;
+ --nldesign-component-button-secondary-action-color: #94d0af;
+ --nldesign-component-button-secondary-action-hover-background-color: #1c2c21;
+ --nldesign-component-content-card-shadow-color: #d2d3d40a;
+ --nldesign-component-content-surface-background-color: #171a20;
+ --nldesign-component-form-field-label-color: #e2e3e4;
+ --nldesign-component-form-fieldset-border-color: #24272d;
+ --nldesign-component-form-select-border-color: #24272d;
+ --nldesign-component-form-select-focus-border-color: #8cc8a7;
+ --nldesign-component-heading-1-color: #e2e3e4;
+ --nldesign-component-heading-2-color: #e2e3e4;
+ --nldesign-component-heading-3-color: #e2e3e4;
+ --nldesign-component-heading-4-color: #e2e3e4;
+ --nldesign-component-heading-5-color: #e2e3e4;
+ --nldesign-component-heading-6-color: #e2e3e4;
+ --nldesign-component-heading-color: #e2e3e4;
+ --nldesign-component-link-color: #94d0af;
+ --nldesign-component-link-hover-color: #b5e0c9;
+ --nldesign-component-link-visited-color: #cea0eb;
+ --nldesign-component-navigation-active-background-color: #cc9414;
+ --nldesign-component-navigation-active-color: #ffde94;
+ --nldesign-component-navigation-badge-background-color: #cc9414;
+ --nldesign-component-navigation-badge-color: #111111;
+ --nldesign-component-ordered-list-color: #e2e3e4;
+ --nldesign-component-paragraph-color: #e2e3e4;
+ --nldesign-component-separator-border-color: #24272d;
+ --nldesign-component-status-badge-error-background-color: #310d0a;
+ --nldesign-component-status-badge-error-color: #ff5c5c;
+ --nldesign-component-status-badge-info-background-color: #1c2c21;
+ --nldesign-component-status-badge-info-color: #b5e0c9;
+ --nldesign-component-status-badge-success-background-color: #192e1e;
+ --nldesign-component-status-badge-success-color: #94e1a0;
+ --nldesign-component-status-badge-warning-background-color: #412d03;
+ --nldesign-component-status-badge-warning-color: #ffd485;
+ --nldesign-component-table-border-color: #24272d;
+ --nldesign-component-table-header-background-color: #1d2026;
+ --nldesign-component-table-header-color: #e2e3e4;
+ --nldesign-component-table-row-hover-background-color: #1d1f23;
+ --nldesign-component-textbox-background-color: #141414;
+ --nldesign-component-textbox-border-color: #5d6474;
+ --nldesign-component-textbox-color: #e2e3e4;
+ --nldesign-component-textbox-disabled-background-color: #2a2a2a;
+ --nldesign-component-textbox-disabled-color: #9e9e9e;
+ --nldesign-component-textbox-focus-border-color: #8cc8a7;
+ --nldesign-component-textbox-hover-border-color: #656c78;
+ --nldesign-component-textbox-invalid-border-color: #f54949;
+ --nldesign-component-unordered-list-color: #e2e3e4;
+ --nldesign-logo-url: url('../../../img/logos/wilgenboom-dark.svg');
+ --wilgenboom-color-accent: #cc9414;
+ --wilgenboom-color-accent-light: #453507;
+ --wilgenboom-color-accent-text: #ffde94;
+ --wilgenboom-color-ink: #d2d3d4;
+ --wilgenboom-color-line: #24272d;
+ --wilgenboom-color-main: #8cc8a7;
+ --wilgenboom-color-main-deep: #a7d6bd;
+ --wilgenboom-color-main-light: #1c2c21;
+ --wilgenboom-color-muted: #93969c;
+ --wilgenboom-color-surface: #171a20;
+ }
+}
+body[data-theme-dark],
+body[data-themes*=dark] {
+ --nldesign-brand-stripe-color-1: #8cc8a7;
+ --nldesign-brand-stripe-color-2: #cc9414;
+ --nldesign-brand-stripe-color-3: #8cc8a7;
+ --nldesign-color-background: #171a20;
+ --nldesign-color-background-dark: #1d2026;
+ --nldesign-color-background-darker: #2d333c;
+ --nldesign-color-background-hover: #1d1f23;
+ --nldesign-color-border: #24272d;
+ --nldesign-color-border-dark: #656c78;
+ --nldesign-color-button-primary-background: #8cc8a7;
+ --nldesign-color-button-primary-border: #8cc8a7;
+ --nldesign-color-button-primary-hover: #a7d6bd;
+ --nldesign-color-button-primary-text: #3e3e3e;
+ --nldesign-color-error: #f54949;
+ --nldesign-color-error-hover: #f65656;
+ --nldesign-color-error-rgb: 245, 73, 73;
+ --nldesign-color-favorite: #f48c25;
+ --nldesign-color-focus: #8cc8a780;
+ --nldesign-color-focus-rgb: 140, 200, 167;
+ --nldesign-color-header-background: #141414;
+ --nldesign-color-header-text: #e2e3e4;
+ --nldesign-color-info: #8cc8a7;
+ --nldesign-color-info-rgb: 140, 200, 167;
+ --nldesign-color-link: #8cc8a7;
+ --nldesign-color-link-hover: #a7d6bd;
+ --nldesign-color-link-visited: #c392e3;
+ --nldesign-color-nav-background: #141414;
+ --nldesign-color-placeholder-dark: #3f3f3f;
+ --nldesign-color-placeholder-light: #2a2a2a;
+ --nldesign-color-primary: #60b988;
+ --nldesign-color-primary-hover: #1f4a33;
+ --nldesign-color-primary-light: #1c2c21;
+ --nldesign-color-primary-light-hover: #24362b;
+ --nldesign-color-primary-text: #111111;
+ --nldesign-color-success: #8ad896;
+ --nldesign-color-success-rgb: 138, 216, 150;
+ --nldesign-color-text: #e2e3e4;
+ --nldesign-color-text-light: #9e9e9e;
+ --nldesign-color-text-muted: #999ca3;
+ --nldesign-color-warning: #f8ca77;
+ --nldesign-color-warning-rgb: 248, 202, 119;
+ --nldesign-component-badge-background-color: #8cc8a7;
+ --nldesign-component-badge-color: #3e3e3e;
+ --nldesign-component-button-active-background-color: #24362b;
+ --nldesign-component-button-active-color: #94d0af;
+ --nldesign-component-button-border-color: #8cc8a7;
+ --nldesign-component-button-color: #94d0af;
+ --nldesign-component-button-disabled-background-color: #2a2a2a;
+ --nldesign-component-button-disabled-border-color: #535353;
+ --nldesign-component-button-disabled-color: #9e9e9e;
+ --nldesign-component-button-error-color: #000000;
+ --nldesign-component-button-focus-border-color: #8cc8a780;
+ --nldesign-component-button-hover-background-color: #1c2c21;
+ --nldesign-component-button-hover-border-color: #a7d6bd;
+ --nldesign-component-button-hover-color: #94d0af;
+ --nldesign-component-button-primary-action-background-color: #8cc8a7;
+ --nldesign-component-button-primary-action-border-color: #8cc8a7;
+ --nldesign-component-button-primary-action-color: #3e3e3e;
+ --nldesign-component-button-primary-action-hover-background-color: #a7d6bd;
+ --nldesign-component-button-primary-action-hover-color: #3e3e3e;
+ --nldesign-component-button-secondary-action-border-color: #8cc8a7;
+ --nldesign-component-button-secondary-action-color: #94d0af;
+ --nldesign-component-button-secondary-action-hover-background-color: #1c2c21;
+ --nldesign-component-content-card-shadow-color: #d2d3d40a;
+ --nldesign-component-content-surface-background-color: #171a20;
+ --nldesign-component-form-field-label-color: #e2e3e4;
+ --nldesign-component-form-fieldset-border-color: #24272d;
+ --nldesign-component-form-select-border-color: #24272d;
+ --nldesign-component-form-select-focus-border-color: #8cc8a7;
+ --nldesign-component-heading-1-color: #e2e3e4;
+ --nldesign-component-heading-2-color: #e2e3e4;
+ --nldesign-component-heading-3-color: #e2e3e4;
+ --nldesign-component-heading-4-color: #e2e3e4;
+ --nldesign-component-heading-5-color: #e2e3e4;
+ --nldesign-component-heading-6-color: #e2e3e4;
+ --nldesign-component-heading-color: #e2e3e4;
+ --nldesign-component-link-color: #94d0af;
+ --nldesign-component-link-hover-color: #b5e0c9;
+ --nldesign-component-link-visited-color: #cea0eb;
+ --nldesign-component-navigation-active-background-color: #cc9414;
+ --nldesign-component-navigation-active-color: #ffde94;
+ --nldesign-component-navigation-badge-background-color: #cc9414;
+ --nldesign-component-navigation-badge-color: #111111;
+ --nldesign-component-ordered-list-color: #e2e3e4;
+ --nldesign-component-paragraph-color: #e2e3e4;
+ --nldesign-component-separator-border-color: #24272d;
+ --nldesign-component-status-badge-error-background-color: #310d0a;
+ --nldesign-component-status-badge-error-color: #ff5c5c;
+ --nldesign-component-status-badge-info-background-color: #1c2c21;
+ --nldesign-component-status-badge-info-color: #b5e0c9;
+ --nldesign-component-status-badge-success-background-color: #192e1e;
+ --nldesign-component-status-badge-success-color: #94e1a0;
+ --nldesign-component-status-badge-warning-background-color: #412d03;
+ --nldesign-component-status-badge-warning-color: #ffd485;
+ --nldesign-component-table-border-color: #24272d;
+ --nldesign-component-table-header-background-color: #1d2026;
+ --nldesign-component-table-header-color: #e2e3e4;
+ --nldesign-component-table-row-hover-background-color: #1d1f23;
+ --nldesign-component-textbox-background-color: #141414;
+ --nldesign-component-textbox-border-color: #5d6474;
+ --nldesign-component-textbox-color: #e2e3e4;
+ --nldesign-component-textbox-disabled-background-color: #2a2a2a;
+ --nldesign-component-textbox-disabled-color: #9e9e9e;
+ --nldesign-component-textbox-focus-border-color: #8cc8a7;
+ --nldesign-component-textbox-hover-border-color: #656c78;
+ --nldesign-component-textbox-invalid-border-color: #f54949;
+ --nldesign-component-unordered-list-color: #e2e3e4;
+ --nldesign-logo-url: url('../../../img/logos/wilgenboom-dark.svg');
+ --wilgenboom-color-accent: #cc9414;
+ --wilgenboom-color-accent-light: #453507;
+ --wilgenboom-color-accent-text: #ffde94;
+ --wilgenboom-color-ink: #d2d3d4;
+ --wilgenboom-color-line: #24272d;
+ --wilgenboom-color-main: #8cc8a7;
+ --wilgenboom-color-main-deep: #a7d6bd;
+ --wilgenboom-color-main-light: #1c2c21;
+ --wilgenboom-color-muted: #93969c;
+ --wilgenboom-color-surface: #171a20;
+}
diff --git a/css/tokens/esdoornveen.css b/css/tokens/esdoornveen.css
new file mode 100644
index 000000000..9604e639f
--- /dev/null
+++ b/css/tokens/esdoornveen.css
@@ -0,0 +1,176 @@
+/**
+ * Esdoornveen, mbo college Design Tokens
+ *
+ * Esdoornveen, mbo college is a school in Zuiddrecht, the demo town that does not exist,
+ * so a demonstration never borrows the house style of a real school. The
+ * palette is Conduction's own design for it (openspec/changes/school-token-sets).
+ * Learning that leads to a trade: practical and grown-up, closer to a professional tool than to a school.
+ *
+ * #5B2E91 (plum) is the interactive colour for buttons, links and focus,
+ * #43206E its hover. #C2255C (maple rose) is the accent, NOT the interactive
+ * primary: it marks the selected navigation entry (a soft wash with a
+ * #9C1C49 label) and the count badge in the navigation. Urgency is always the
+ * red status colour with words, never the accent alone.
+ *
+ * THE WORKPLACE LOOK. Like zuiddrecht, this set wears the light workplace
+ * layout: a white top bar with dark text, a white app navigation, a grey
+ * workspace (#F5F6F8) and white cards with a hairline border. token-sets.json
+ * turns the workplace layout on for this set (its `layout` block), and an
+ * administrator can switch it off again.
+ *
+ * Every text pair below reaches WCAG AA (4.5:1), computed, not estimated:
+ * white on #5B2E91 9.36, #5B2E91 on white 9.36 and on the workspace 8.65,
+ * #43206E on #F0EAF7 10.67, #1B1C1D on white 17.07, #5E6168 on white 6.20 and
+ * on the workspace 5.74, #B30000 on white 7.20 and on the workspace
+ * 6.66, #9C1C49 on the selected-entry wash #F5DCE5 6.07,
+ * #ffffff on #C2255C 5.66, #1E6B2A on #E7F3EA 5.77, #7A4F00 on #FFF4DE
+ * 6.53, #A30000 on #FCEDEC 7.22.
+ */
+
+:root {
+ /* Primary interactive colour */
+ --nldesign-color-primary: #5B2E91;
+ --nldesign-color-primary-text: #ffffff;
+ --nldesign-color-primary-hover: #43206E;
+ --nldesign-color-primary-light: #F0EAF7;
+ /* Not in the design: the primary-light tint with 7% of the primary mixed
+ * in, the step zuiddrecht's #DCE6F2 takes from its #EAF0F7. */
+ --nldesign-color-primary-light-hover: #E6DDF0;
+
+ /* Esdoornveen, mbo college palette */
+ --esdoornveen-color-main: #5B2E91;
+ --esdoornveen-color-main-deep: #43206E;
+ --esdoornveen-color-main-light: #F0EAF7;
+ --esdoornveen-color-accent: #C2255C;
+ --esdoornveen-color-accent-light: #FBE9F0;
+ --esdoornveen-color-accent-text: #9C1C49;
+ --esdoornveen-color-ink: #1B1C1D;
+ --esdoornveen-color-muted: #5E6168;
+ --esdoornveen-color-line: #E4E6EA;
+ --esdoornveen-color-surface: #F5F6F8;
+
+ /* Codes (crebo numbers, exam codes) in IBM Plex Mono. No layer reads a
+ * code face yet, so it is a palette entry the apps can pick up. */
+ --esdoornveen-font-family-code: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
+
+ /* Logo image */
+ --nldesign-logo-url: url('../../img/logos/esdoornveen.svg');
+ /* The logo is a wordmark, 3.97 times as wide as it is high.
+ * 127px gives it 32px of height in Nextcloud's header. */
+ --nldesign-logo-width: 127px;
+
+ /* Background colours, for hover states and the darker steps. The main
+ * background is managed by Nextcloud's theming system. */
+ --nldesign-color-background-hover: #F0F1F3;
+ --nldesign-color-background-dark: #EDEFF2;
+ --nldesign-color-background-darker: #D3D8DF;
+
+ /* Header: white with dark text and a hairline under it (as zuiddrecht) */
+ --nldesign-color-header-background: #ffffff;
+ --nldesign-color-header-text: #1B1C1D;
+ --nldesign-header-border-bottom: 1px solid rgba(138, 146, 158, 0.25);
+
+ /* Navigation */
+ --nldesign-color-nav-background: #ffffff;
+
+ /* Text colours: Cunningham's ink, and #5E6168 for muted text (Cunningham's
+ * own #74777c is 4.49:1 on white, just under AA). */
+ --nldesign-color-text: #1B1C1D;
+ --nldesign-color-text-muted: #5E6168;
+ --nldesign-color-text-light: #ffffff;
+
+ /* Status colours. Error is the design's #B30000; its hover is the dark red
+ * of the overdue pill. */
+ --nldesign-color-error: #B30000;
+ --nldesign-color-error-rgb: 179, 0, 0;
+ --nldesign-color-error-hover: #A30000;
+ --nldesign-color-warning: #7A4F00;
+ --nldesign-color-warning-rgb: 122, 79, 0;
+ --nldesign-color-success: #1E6B2A;
+ --nldesign-color-success-rgb: 30, 107, 42;
+ --nldesign-color-info: #5B2E91;
+ --nldesign-color-info-rgb: 91, 46, 145;
+
+ /* Border colours. The hairline is for cards and dividers. The design's
+ * field border #C4C7CB is 1.7:1 against white, under the 3:1 a control
+ * border needs, so controls take zuiddrecht's #8A929E (3.14). */
+ --nldesign-color-border: #E4E6EA;
+ --nldesign-color-border-dark: #8A929E;
+
+ /* Focus colour */
+ --nldesign-color-focus: rgba(91, 46, 145, 0.5);
+ --nldesign-color-focus-rgb: 91, 46, 145;
+
+ /* Link colours (the interactive colour, not the accent) */
+ --nldesign-color-link: #5B2E91;
+ --nldesign-color-link-hover: #43206E;
+
+ /* Button colours */
+ --nldesign-color-button-primary-background: #5B2E91;
+ --nldesign-color-button-primary-text: #ffffff;
+ --nldesign-color-button-primary-border: #5B2E91;
+ --nldesign-color-button-primary-hover: #43206E;
+
+ /* Typography: IBM Plex Sans in 400, 500, 600 and 700, and IBM Plex Mono in 400 and 500 for codes such as crebo numbers and exam codes, both bundled by thematiq. */
+ --nldesign-font-family: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
+
+ /* Border radius: NEXTCLOUD'S SCALE, NOT THE WEBSITE'S. The workplace keeps
+ * 8px controls and 12px containers, for the reason zuiddrecht.css and
+ * cunningham.css give: a near-square or rounder brand radius would reshape
+ * the Nextcloud chrome. Literals, not var(): overrides.css maps
+ * Nextcloud's scale FROM these tokens. */
+ --nldesign-border-radius: 8px;
+ --nldesign-border-radius-small: 4px;
+ --nldesign-border-radius-large: 12px;
+ --nldesign-border-radius-rounded: 28px;
+ --nldesign-border-radius-pill: 100px;
+
+ /* The website's own corners: 4px for buttons and fields, 8px for cards.
+ * Only css/public-bridge.css reads these, on a public portal. */
+ --nldesign-website-border-radius: 4px;
+ --nldesign-website-border-radius-large: 8px;
+
+ /* The selected navigation entry: the accent, where Nextcloud uses the
+ * primary colour. Nextcloud 34 and later draw it as a 16% wash of this
+ * colour (#F5DCE5 on white, the design's #FBE9F0) with the
+ * #9C1C49 label on it at 6.07:1. */
+ --nldesign-component-navigation-active-background-color: #C2255C;
+ --nldesign-component-navigation-active-color: #9C1C49;
+
+ /* The count badge in the navigation: the accent with white on it (5.66:1). */
+ --nldesign-component-navigation-badge-background-color: #C2255C;
+ --nldesign-component-navigation-badge-color: #ffffff;
+
+ /* The workspace: a grey surface that white cards sit on, with a very
+ * light shadow (4% ink). */
+ --nldesign-component-content-surface-background-color: #F5F6F8;
+ --nldesign-component-content-card-shadow-color: rgba(27, 28, 29, 0.04);
+
+ /* Status pills, fixed for the four school sets: received is the
+ * primary's own tint. info 10.67:1, success 5.77:1, warning 6.53:1, error 7.22:1. */
+ --nldesign-component-status-badge-info-background-color: #F0EAF7;
+ --nldesign-component-status-badge-info-color: #43206E;
+ --nldesign-component-status-badge-success-background-color: #E7F3EA;
+ --nldesign-component-status-badge-success-color: #1E6B2A;
+ --nldesign-component-status-badge-warning-background-color: #FFF4DE;
+ --nldesign-component-status-badge-warning-color: #7A4F00;
+ --nldesign-component-status-badge-error-background-color: #FCEDEC;
+ --nldesign-component-status-badge-error-color: #A30000;
+
+ /* The login watermark: the emblem in grey, large and faint, in the bottom
+ * corner of the login page while the workplace layout is light. */
+ --nldesign-login-watermark-image: url('../../img/logos/esdoornveen-emblem-grey.svg');
+ --nldesign-login-watermark-opacity: 0.06;
+
+ /* The motif, "de snede": a slanted cut like the edge of a maple leaf, a 6px plum band with one rose segment whose ends are cut at 32 degrees. Drawn
+ * along the top bar and the login card while the brand stripe is on.
+ * The segment is the one on the designed login card: 96px wide, 32px from the start, its ends slanted as skewX(-32deg) draws them. A gradient at 122 degrees has edges 32 degrees off vertical, and along it a point at x and mid-height y = 3 lies at 0.848x + 1.59px, so 32px and 128px become 28.73px and 110.13px. The three colours are for the component library, which draws flat bands only: plum, rose, plum in the ratio 1 : 3 : 10. */
+ --nldesign-brand-stripe-color-1: #5B2E91;
+ --nldesign-brand-stripe-color-2: #C2255C;
+ --nldesign-brand-stripe-color-3: #5B2E91;
+ --nldesign-brand-stripe-ratio-1: 1;
+ --nldesign-brand-stripe-ratio-2: 3;
+ --nldesign-brand-stripe-ratio-3: 10;
+ --nldesign-brand-stripe-height: 6px;
+ --nldesign-brand-stripe-image: linear-gradient(122deg, #5B2E91 0 28.73px, #C2255C 28.73px 110.13px, #5B2E91 110.13px);
+}
diff --git a/css/tokens/vaartveld.css b/css/tokens/vaartveld.css
new file mode 100644
index 000000000..26d053685
--- /dev/null
+++ b/css/tokens/vaartveld.css
@@ -0,0 +1,176 @@
+/**
+ * Vaartveld College Design Tokens
+ *
+ * Vaartveld College is a school in Zuiddrecht, the demo town that does not exist,
+ * so a demonstration never borrows the house style of a real school. The
+ * palette is Conduction's own design for it (openspec/changes/school-token-sets).
+ * The long view down the canal: clear, confident and a little bold, for pupils of 12 to 18.
+ *
+ * #1F4FD8 (cobalt) is the interactive colour for buttons, links and focus,
+ * #14338F its hover. #1FB5A8 (aqua) is the accent, NOT the interactive
+ * primary: it marks the selected navigation entry (a soft wash with a
+ * #0B6259 label) and the count badge in the navigation. Urgency is always the
+ * red status colour with words, never the accent alone.
+ *
+ * THE WORKPLACE LOOK. Like zuiddrecht, this set wears the light workplace
+ * layout: a white top bar with dark text, a white app navigation, a grey
+ * workspace (#F5F6F8) and white cards with a hairline border. token-sets.json
+ * turns the workplace layout on for this set (its `layout` block), and an
+ * administrator can switch it off again.
+ *
+ * Every text pair below reaches WCAG AA (4.5:1), computed, not estimated:
+ * white on #1F4FD8 6.63, #1F4FD8 on white 6.63 and on the workspace 6.13,
+ * #14338F on #E8EEFC 9.51, #1B1C1D on white 17.07, #5E6168 on white 6.20 and
+ * on the workspace 5.74, #B30000 on white 7.20 and on the workspace
+ * 6.66, #0B6259 on the selected-entry wash #DBF3F1 6.23,
+ * #1A1A1A on #1FB5A8 6.82, #1E6B2A on #E7F3EA 5.77, #7A4F00 on #FFF4DE
+ * 6.53, #A30000 on #FCEDEC 7.22.
+ */
+
+:root {
+ /* Primary interactive colour */
+ --nldesign-color-primary: #1F4FD8;
+ --nldesign-color-primary-text: #ffffff;
+ --nldesign-color-primary-hover: #14338F;
+ --nldesign-color-primary-light: #E8EEFC;
+ /* Not in the design: the primary-light tint with 7% of the primary mixed
+ * in, the step zuiddrecht's #DCE6F2 takes from its #EAF0F7. */
+ --nldesign-color-primary-light-hover: #DAE3F9;
+
+ /* Vaartveld College palette */
+ --vaartveld-color-main: #1F4FD8;
+ --vaartveld-color-main-deep: #14338F;
+ --vaartveld-color-main-light: #E8EEFC;
+ --vaartveld-color-accent: #1FB5A8;
+ --vaartveld-color-accent-light: #DDF5F2;
+ --vaartveld-color-accent-text: #0B6259;
+ --vaartveld-color-ink: #1B1C1D;
+ --vaartveld-color-muted: #5E6168;
+ --vaartveld-color-line: #E4E6EA;
+ --vaartveld-color-surface: #F5F6F8;
+
+ /* Logo image */
+ --nldesign-logo-url: url('../../img/logos/vaartveld.svg');
+ /* The logo is a wordmark, 3.47 times as wide as it is high.
+ * 111px gives it 32px of height in Nextcloud's header. */
+ --nldesign-logo-width: 111px;
+
+ /* Background colours, for hover states and the darker steps. The main
+ * background is managed by Nextcloud's theming system. */
+ --nldesign-color-background-hover: #F0F1F3;
+ --nldesign-color-background-dark: #EDEFF2;
+ --nldesign-color-background-darker: #D3D8DF;
+
+ /* Header: white with dark text and a hairline under it (as zuiddrecht) */
+ --nldesign-color-header-background: #ffffff;
+ --nldesign-color-header-text: #1B1C1D;
+ --nldesign-header-border-bottom: 1px solid rgba(138, 146, 158, 0.25);
+
+ /* Navigation */
+ --nldesign-color-nav-background: #ffffff;
+
+ /* Text colours: Cunningham's ink, and #5E6168 for muted text (Cunningham's
+ * own #74777c is 4.49:1 on white, just under AA). */
+ --nldesign-color-text: #1B1C1D;
+ --nldesign-color-text-muted: #5E6168;
+ --nldesign-color-text-light: #ffffff;
+
+ /* Status colours. Error is the design's #B30000; its hover is the dark red
+ * of the overdue pill. */
+ --nldesign-color-error: #B30000;
+ --nldesign-color-error-rgb: 179, 0, 0;
+ --nldesign-color-error-hover: #A30000;
+ --nldesign-color-warning: #7A4F00;
+ --nldesign-color-warning-rgb: 122, 79, 0;
+ --nldesign-color-success: #1E6B2A;
+ --nldesign-color-success-rgb: 30, 107, 42;
+ --nldesign-color-info: #1F4FD8;
+ --nldesign-color-info-rgb: 31, 79, 216;
+
+ /* Border colours. The hairline is for cards and dividers. The design's
+ * field border #C4C7CB is 1.7:1 against white, under the 3:1 a control
+ * border needs, so controls take zuiddrecht's #8A929E (3.14). */
+ --nldesign-color-border: #E4E6EA;
+ --nldesign-color-border-dark: #8A929E;
+
+ /* Focus colour */
+ --nldesign-color-focus: rgba(31, 79, 216, 0.5);
+ --nldesign-color-focus-rgb: 31, 79, 216;
+
+ /* Link colours (the interactive colour, not the accent) */
+ --nldesign-color-link: #1F4FD8;
+ --nldesign-color-link-hover: #14338F;
+
+ /* Button colours */
+ --nldesign-color-button-primary-background: #1F4FD8;
+ --nldesign-color-button-primary-text: #ffffff;
+ --nldesign-color-button-primary-border: #1F4FD8;
+ --nldesign-color-button-primary-hover: #14338F;
+
+ /* Typography: Red Hat Text in 400, 500, 600 and 700 for text, Red Hat Display in 600, 700 and 800 for headings, both bundled by thematiq. */
+ --nldesign-font-family: 'Red Hat Text', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
+
+ /* Headings: their own face. Nextcloud's headings read this token, and
+ * css/public-bridge.css hands it to the website's headings. */
+ --nldesign-component-heading-font-family: 'Red Hat Display', 'Red Hat Text', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
+
+ /* Border radius: NEXTCLOUD'S SCALE, NOT THE WEBSITE'S. The workplace keeps
+ * 8px controls and 12px containers, for the reason zuiddrecht.css and
+ * cunningham.css give: a near-square or rounder brand radius would reshape
+ * the Nextcloud chrome. Literals, not var(): overrides.css maps
+ * Nextcloud's scale FROM these tokens. */
+ --nldesign-border-radius: 8px;
+ --nldesign-border-radius-small: 4px;
+ --nldesign-border-radius-large: 12px;
+ --nldesign-border-radius-rounded: 28px;
+ --nldesign-border-radius-pill: 100px;
+
+ /* The website's own corners: 6px for buttons and fields, 10px for cards.
+ * Only css/public-bridge.css reads these, on a public portal. */
+ --nldesign-website-border-radius: 6px;
+ --nldesign-website-border-radius-large: 10px;
+
+ /* The selected navigation entry: the accent, where Nextcloud uses the
+ * primary colour. Nextcloud 34 and later draw it as a 16% wash of this
+ * colour (#DBF3F1 on white, the design's #DDF5F2) with the
+ * #0B6259 label on it at 6.23:1. */
+ --nldesign-component-navigation-active-background-color: #1FB5A8;
+ --nldesign-component-navigation-active-color: #0B6259;
+
+ /* The count badge in the navigation: the accent with ink on it (6.82:1). */
+ --nldesign-component-navigation-badge-background-color: #1FB5A8;
+ --nldesign-component-navigation-badge-color: #1A1A1A;
+
+ /* The workspace: a grey surface that white cards sit on, with a very
+ * light shadow (4% ink). */
+ --nldesign-component-content-surface-background-color: #F5F6F8;
+ --nldesign-component-content-card-shadow-color: rgba(27, 28, 29, 0.04);
+
+ /* Status pills, fixed for the four school sets: received is the
+ * primary's own tint. info 9.51:1, success 5.77:1, warning 6.53:1, error 7.22:1. */
+ --nldesign-component-status-badge-info-background-color: #E8EEFC;
+ --nldesign-component-status-badge-info-color: #14338F;
+ --nldesign-component-status-badge-success-background-color: #E7F3EA;
+ --nldesign-component-status-badge-success-color: #1E6B2A;
+ --nldesign-component-status-badge-warning-background-color: #FFF4DE;
+ --nldesign-component-status-badge-warning-color: #7A4F00;
+ --nldesign-component-status-badge-error-background-color: #FCEDEC;
+ --nldesign-component-status-badge-error-color: #A30000;
+
+ /* The login watermark: the emblem in grey, large and faint, in the bottom
+ * corner of the login page while the workplace layout is light. */
+ --nldesign-login-watermark-image: url('../../img/logos/vaartveld-emblem-grey.svg');
+ --nldesign-login-watermark-opacity: 0.08;
+
+ /* The motif, "de vaart": the canal and its bank, a 4px cobalt line, 3px of ground and a 2px aqua line. Drawn
+ * along the top bar and the login card while the brand stripe is on.
+ * The 3px between the two lines is transparent rather than white, so it is the ground of the bar it sits on in the dark as well. The three colours are for the component library, which draws flat bands only: cobalt, aqua, cobalt in the ratio 4 : 2 : 4, the weights of the two lines. */
+ --nldesign-brand-stripe-color-1: #1F4FD8;
+ --nldesign-brand-stripe-color-2: #1FB5A8;
+ --nldesign-brand-stripe-color-3: #1F4FD8;
+ --nldesign-brand-stripe-ratio-1: 4;
+ --nldesign-brand-stripe-ratio-2: 2;
+ --nldesign-brand-stripe-ratio-3: 4;
+ --nldesign-brand-stripe-height: 9px;
+ --nldesign-brand-stripe-image: linear-gradient(to bottom, #1F4FD8 0 4px, transparent 4px 7px, #1FB5A8 7px 9px);
+}
diff --git a/css/tokens/warmtepompacademie.css b/css/tokens/warmtepompacademie.css
new file mode 100644
index 000000000..3176c239b
--- /dev/null
+++ b/css/tokens/warmtepompacademie.css
@@ -0,0 +1,176 @@
+/**
+ * Warmtepompacademie Design Tokens
+ *
+ * Warmtepompacademie is a school in Zuiddrecht, the demo town that does not exist,
+ * so a demonstration never borrows the house style of a real school. The
+ * palette is Conduction's own design for it (openspec/changes/school-token-sets).
+ * Heat moves from cold to warm: a trade academy for installers, exact and technical.
+ *
+ * #0B6E7A (petrol, the cold side) is the interactive colour for buttons, links and focus,
+ * #084F58 its hover. #C2410C (ember, the warm side) is the accent, NOT the interactive
+ * primary: it marks the selected navigation entry (a soft wash with a
+ * #9A3412 label) and the count badge in the navigation. Urgency is always the
+ * red status colour with words, never the accent alone.
+ *
+ * THE WORKPLACE LOOK. Like zuiddrecht, this set wears the light workplace
+ * layout: a white top bar with dark text, a white app navigation, a grey
+ * workspace (#F5F6F8) and white cards with a hairline border. token-sets.json
+ * turns the workplace layout on for this set (its `layout` block), and an
+ * administrator can switch it off again.
+ *
+ * Every text pair below reaches WCAG AA (4.5:1), computed, not estimated:
+ * white on #0B6E7A 5.96, #0B6E7A on white 5.96 and on the workspace 5.51,
+ * #084F58 on #E3F1F3 7.99, #1B1C1D on white 17.07, #5E6168 on white 6.20 and
+ * on the workspace 5.74, #B30000 on white 7.20 and on the workspace
+ * 6.66, #9A3412 on the selected-entry wash #F5E1D8 5.79,
+ * #ffffff on #C2410C 5.18, #1E6B2A on #E7F3EA 5.77, #7A4F00 on #FFF4DE
+ * 6.53, #A30000 on #FCEDEC 7.22.
+ */
+
+:root {
+ /* Primary interactive colour */
+ --nldesign-color-primary: #0B6E7A;
+ --nldesign-color-primary-text: #ffffff;
+ --nldesign-color-primary-hover: #084F58;
+ --nldesign-color-primary-light: #E3F1F3;
+ /* Not in the design: the primary-light tint with 7% of the primary mixed
+ * in, the step zuiddrecht's #DCE6F2 takes from its #EAF0F7. */
+ --nldesign-color-primary-light-hover: #D4E8EB;
+
+ /* Warmtepompacademie palette */
+ --warmtepompacademie-color-main: #0B6E7A;
+ --warmtepompacademie-color-main-deep: #084F58;
+ --warmtepompacademie-color-main-light: #E3F1F3;
+ --warmtepompacademie-color-accent: #C2410C;
+ --warmtepompacademie-color-accent-light: #FCEBDD;
+ --warmtepompacademie-color-accent-text: #9A3412;
+ --warmtepompacademie-color-accent-mark: #D9480F;
+ --warmtepompacademie-color-ink: #1B1C1D;
+ --warmtepompacademie-color-muted: #5E6168;
+ --warmtepompacademie-color-line: #E4E6EA;
+ --warmtepompacademie-color-surface: #F5F6F8;
+
+ /* Logo image */
+ --nldesign-logo-url: url('../../img/logos/warmtepompacademie.svg');
+ /* The logo is a wordmark, 3.78 times as wide as it is high.
+ * 121px gives it 32px of height in Nextcloud's header. */
+ --nldesign-logo-width: 121px;
+
+ /* Background colours, for hover states and the darker steps. The main
+ * background is managed by Nextcloud's theming system. */
+ --nldesign-color-background-hover: #F0F1F3;
+ --nldesign-color-background-dark: #EDEFF2;
+ --nldesign-color-background-darker: #D3D8DF;
+
+ /* Header: white with dark text and a hairline under it (as zuiddrecht) */
+ --nldesign-color-header-background: #ffffff;
+ --nldesign-color-header-text: #1B1C1D;
+ --nldesign-header-border-bottom: 1px solid rgba(138, 146, 158, 0.25);
+
+ /* Navigation */
+ --nldesign-color-nav-background: #ffffff;
+
+ /* Text colours: Cunningham's ink, and #5E6168 for muted text (Cunningham's
+ * own #74777c is 4.49:1 on white, just under AA). */
+ --nldesign-color-text: #1B1C1D;
+ --nldesign-color-text-muted: #5E6168;
+ --nldesign-color-text-light: #ffffff;
+
+ /* Status colours. Error is the design's #B30000; its hover is the dark red
+ * of the overdue pill. */
+ --nldesign-color-error: #B30000;
+ --nldesign-color-error-rgb: 179, 0, 0;
+ --nldesign-color-error-hover: #A30000;
+ --nldesign-color-warning: #7A4F00;
+ --nldesign-color-warning-rgb: 122, 79, 0;
+ --nldesign-color-success: #1E6B2A;
+ --nldesign-color-success-rgb: 30, 107, 42;
+ --nldesign-color-info: #0B6E7A;
+ --nldesign-color-info-rgb: 11, 110, 122;
+
+ /* Border colours. The hairline is for cards and dividers. The design's
+ * field border #C4C7CB is 1.7:1 against white, under the 3:1 a control
+ * border needs, so controls take zuiddrecht's #8A929E (3.14). */
+ --nldesign-color-border: #E4E6EA;
+ --nldesign-color-border-dark: #8A929E;
+
+ /* Focus colour */
+ --nldesign-color-focus: rgba(11, 110, 122, 0.5);
+ --nldesign-color-focus-rgb: 11, 110, 122;
+
+ /* Link colours (the interactive colour, not the accent) */
+ --nldesign-color-link: #0B6E7A;
+ --nldesign-color-link-hover: #084F58;
+
+ /* Button colours */
+ --nldesign-color-button-primary-background: #0B6E7A;
+ --nldesign-color-button-primary-text: #ffffff;
+ --nldesign-color-button-primary-border: #0B6E7A;
+ --nldesign-color-button-primary-hover: #084F58;
+
+ /* Typography: Barlow in 400, 500, 600 and 700 for text, Barlow Semi Condensed in 600 and 700 for headings and numbers, both bundled by thematiq. */
+ --nldesign-font-family: 'Barlow', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
+
+ /* Headings: their own face. Nextcloud's headings read this token, and
+ * css/public-bridge.css hands it to the website's headings. */
+ --nldesign-component-heading-font-family: 'Barlow Semi Condensed', 'Barlow', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
+
+ /* Border radius: NEXTCLOUD'S SCALE, NOT THE WEBSITE'S. The workplace keeps
+ * 8px controls and 12px containers, for the reason zuiddrecht.css and
+ * cunningham.css give: a near-square or rounder brand radius would reshape
+ * the Nextcloud chrome. Literals, not var(): overrides.css maps
+ * Nextcloud's scale FROM these tokens. */
+ --nldesign-border-radius: 8px;
+ --nldesign-border-radius-small: 4px;
+ --nldesign-border-radius-large: 12px;
+ --nldesign-border-radius-rounded: 28px;
+ --nldesign-border-radius-pill: 100px;
+
+ /* The website's own corners: 3px for buttons and fields, 6px for cards.
+ * Only css/public-bridge.css reads these, on a public portal. */
+ --nldesign-website-border-radius: 3px;
+ --nldesign-website-border-radius-large: 6px;
+
+ /* The selected navigation entry: the accent, where Nextcloud uses the
+ * primary colour. Nextcloud 34 and later draw it as a 16% wash of this
+ * colour (#F5E1D8 on white, the design's #FCEBDD) with the
+ * #9A3412 label on it at 5.79:1. */
+ --nldesign-component-navigation-active-background-color: #C2410C;
+ --nldesign-component-navigation-active-color: #9A3412;
+
+ /* The count badge in the navigation: the accent with white on it (5.18:1). */
+ --nldesign-component-navigation-badge-background-color: #C2410C;
+ --nldesign-component-navigation-badge-color: #ffffff;
+
+ /* The workspace: a grey surface that white cards sit on, with a very
+ * light shadow (4% ink). */
+ --nldesign-component-content-surface-background-color: #F5F6F8;
+ --nldesign-component-content-card-shadow-color: rgba(27, 28, 29, 0.04);
+
+ /* Status pills, fixed for the four school sets: received is the
+ * primary's own tint. info 7.99:1, success 5.77:1, warning 6.53:1, error 7.22:1. */
+ --nldesign-component-status-badge-info-background-color: #E3F1F3;
+ --nldesign-component-status-badge-info-color: #084F58;
+ --nldesign-component-status-badge-success-background-color: #E7F3EA;
+ --nldesign-component-status-badge-success-color: #1E6B2A;
+ --nldesign-component-status-badge-warning-background-color: #FFF4DE;
+ --nldesign-component-status-badge-warning-color: #7A4F00;
+ --nldesign-component-status-badge-error-background-color: #FCEDEC;
+ --nldesign-component-status-badge-error-color: #A30000;
+
+ /* The login watermark: the emblem in grey, large and faint, in the bottom
+ * corner of the login page while the workplace layout is light. */
+ --nldesign-login-watermark-image: url('../../img/logos/warmtepompacademie-emblem-grey.svg');
+
+ /* The motif, "de temperatuurlijn": a 5px line in five hard steps from cold to warm, no gradient: #0B6E7A, #5FA3A8, #E4E6EA, #EFA06F and #D9480F in the ratio 8 : 3 : 2 : 3 : 8. Drawn
+ * along the top bar and the login card while the brand stripe is on.
+ * The three colours are for the component library, which draws three flat bands only: the cold half, the neutral middle and the warm half, 11 : 2 : 11. */
+ --nldesign-brand-stripe-color-1: #0B6E7A;
+ --nldesign-brand-stripe-color-2: #E4E6EA;
+ --nldesign-brand-stripe-color-3: #D9480F;
+ --nldesign-brand-stripe-ratio-1: 11;
+ --nldesign-brand-stripe-ratio-2: 2;
+ --nldesign-brand-stripe-ratio-3: 11;
+ --nldesign-brand-stripe-height: 5px;
+ --nldesign-brand-stripe-image: linear-gradient(to right, #0B6E7A 0 33.333%, #5FA3A8 33.333% 45.833%, #E4E6EA 45.833% 54.167%, #EFA06F 54.167% 66.667%, #D9480F 66.667%);
+}
diff --git a/css/tokens/wilgenboom.css b/css/tokens/wilgenboom.css
new file mode 100644
index 000000000..b2b03aa04
--- /dev/null
+++ b/css/tokens/wilgenboom.css
@@ -0,0 +1,171 @@
+/**
+ * Basisschool De Wilgenboom Design Tokens
+ *
+ * Basisschool De Wilgenboom is a school in Zuiddrecht, the demo town that does not exist,
+ * so a demonstration never borrows the house style of a real school. The
+ * palette is Conduction's own design for it (openspec/changes/school-token-sets).
+ * The tree you shelter under: warm, calm and clear for busy parents.
+ *
+ * #2F6B4A (willow green) is the interactive colour for buttons, links and focus,
+ * #1F4A33 its hover. #F5B82E (sun yellow) is the accent, NOT the interactive
+ * primary: it marks the selected navigation entry (a soft wash with a
+ * #6B4A00 label) and the count badge in the navigation. Urgency is always the
+ * red status colour with words, never the accent alone.
+ *
+ * THE WORKPLACE LOOK. Like zuiddrecht, this set wears the light workplace
+ * layout: a white top bar with dark text, a white app navigation, a grey
+ * workspace (#F5F6F8) and white cards with a hairline border. token-sets.json
+ * turns the workplace layout on for this set (its `layout` block), and an
+ * administrator can switch it off again.
+ *
+ * Every text pair below reaches WCAG AA (4.5:1), computed, not estimated:
+ * white on #2F6B4A 6.32, #2F6B4A on white 6.32 and on the workspace 5.84,
+ * #1F4A33 on #E8F1EB 8.73, #1B1C1D on white 17.07, #5E6168 on white 6.20 and
+ * on the workspace 5.74, #B30000 on white 7.20 and on the workspace
+ * 6.66, #6B4A00 on the selected-entry wash #FDF4DE 7.36,
+ * #1A1A1A on #F5B82E 9.76, #1E6B2A on #E7F3EA 5.77, #7A4F00 on #FFF4DE
+ * 6.53, #A30000 on #FCEDEC 7.22.
+ */
+
+:root {
+ /* Primary interactive colour */
+ --nldesign-color-primary: #2F6B4A;
+ --nldesign-color-primary-text: #ffffff;
+ --nldesign-color-primary-hover: #1F4A33;
+ --nldesign-color-primary-light: #E8F1EB;
+ /* Not in the design: the primary-light tint with 7% of the primary mixed
+ * in, the step zuiddrecht's #DCE6F2 takes from its #EAF0F7. */
+ --nldesign-color-primary-light-hover: #DBE8E0;
+
+ /* Basisschool De Wilgenboom palette */
+ --wilgenboom-color-main: #2F6B4A;
+ --wilgenboom-color-main-deep: #1F4A33;
+ --wilgenboom-color-main-light: #E8F1EB;
+ --wilgenboom-color-accent: #F5B82E;
+ --wilgenboom-color-accent-light: #FDF3D7;
+ --wilgenboom-color-accent-text: #6B4A00;
+ --wilgenboom-color-ink: #1B1C1D;
+ --wilgenboom-color-muted: #5E6168;
+ --wilgenboom-color-line: #E4E6EA;
+ --wilgenboom-color-surface: #F5F6F8;
+
+ /* Logo image */
+ --nldesign-logo-url: url('../../img/logos/wilgenboom.svg');
+ /* The logo is a wordmark, 4.77 times as wide as it is high.
+ * 153px gives it 32px of height in Nextcloud's header. */
+ --nldesign-logo-width: 153px;
+
+ /* Background colours, for hover states and the darker steps. The main
+ * background is managed by Nextcloud's theming system. */
+ --nldesign-color-background-hover: #F0F1F3;
+ --nldesign-color-background-dark: #EDEFF2;
+ --nldesign-color-background-darker: #D3D8DF;
+
+ /* Header: white with dark text and a hairline under it (as zuiddrecht) */
+ --nldesign-color-header-background: #ffffff;
+ --nldesign-color-header-text: #1B1C1D;
+ --nldesign-header-border-bottom: 1px solid rgba(138, 146, 158, 0.25);
+
+ /* Navigation */
+ --nldesign-color-nav-background: #ffffff;
+
+ /* Text colours: Cunningham's ink, and #5E6168 for muted text (Cunningham's
+ * own #74777c is 4.49:1 on white, just under AA). */
+ --nldesign-color-text: #1B1C1D;
+ --nldesign-color-text-muted: #5E6168;
+ --nldesign-color-text-light: #ffffff;
+
+ /* Status colours. Error is the design's #B30000; its hover is the dark red
+ * of the overdue pill. */
+ --nldesign-color-error: #B30000;
+ --nldesign-color-error-rgb: 179, 0, 0;
+ --nldesign-color-error-hover: #A30000;
+ --nldesign-color-warning: #7A4F00;
+ --nldesign-color-warning-rgb: 122, 79, 0;
+ --nldesign-color-success: #1E6B2A;
+ --nldesign-color-success-rgb: 30, 107, 42;
+ --nldesign-color-info: #2F6B4A;
+ --nldesign-color-info-rgb: 47, 107, 74;
+
+ /* Border colours. The hairline is for cards and dividers. The design's
+ * field border #C4C7CB is 1.7:1 against white, under the 3:1 a control
+ * border needs, so controls take zuiddrecht's #8A929E (3.14). */
+ --nldesign-color-border: #E4E6EA;
+ --nldesign-color-border-dark: #8A929E;
+
+ /* Focus colour */
+ --nldesign-color-focus: rgba(47, 107, 74, 0.5);
+ --nldesign-color-focus-rgb: 47, 107, 74;
+
+ /* Link colours (the interactive colour, not the accent) */
+ --nldesign-color-link: #2F6B4A;
+ --nldesign-color-link-hover: #1F4A33;
+
+ /* Button colours */
+ --nldesign-color-button-primary-background: #2F6B4A;
+ --nldesign-color-button-primary-text: #ffffff;
+ --nldesign-color-button-primary-border: #2F6B4A;
+ --nldesign-color-button-primary-hover: #1F4A33;
+
+ /* Typography: Lexend in 400, 500, 600 and 700, bundled by thematiq. It was designed for reading ease, which is the school's subject. */
+ --nldesign-font-family: 'Lexend', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
+
+ /* Border radius: NEXTCLOUD'S SCALE, NOT THE WEBSITE'S. The workplace keeps
+ * 8px controls and 12px containers, for the reason zuiddrecht.css and
+ * cunningham.css give: a near-square or rounder brand radius would reshape
+ * the Nextcloud chrome. Literals, not var(): overrides.css maps
+ * Nextcloud's scale FROM these tokens. */
+ --nldesign-border-radius: 8px;
+ --nldesign-border-radius-small: 4px;
+ --nldesign-border-radius-large: 12px;
+ --nldesign-border-radius-rounded: 28px;
+ --nldesign-border-radius-pill: 100px;
+
+ /* The website's own corners: 10px for buttons and fields, 14px for cards.
+ * Only css/public-bridge.css reads these, on a public portal. */
+ --nldesign-website-border-radius: 10px;
+ --nldesign-website-border-radius-large: 14px;
+
+ /* The selected navigation entry: the accent, where Nextcloud uses the
+ * primary colour. Nextcloud 34 and later draw it as a 16% wash of this
+ * colour (#FDF4DE on white, the design's #FDF3D7) with the
+ * #6B4A00 label on it at 7.36:1. */
+ --nldesign-component-navigation-active-background-color: #F5B82E;
+ --nldesign-component-navigation-active-color: #6B4A00;
+
+ /* The count badge in the navigation: the accent with ink on it (9.76:1). */
+ --nldesign-component-navigation-badge-background-color: #F5B82E;
+ --nldesign-component-navigation-badge-color: #1A1A1A;
+
+ /* The workspace: a grey surface that white cards sit on, with a very
+ * light shadow (4% ink). */
+ --nldesign-component-content-surface-background-color: #F5F6F8;
+ --nldesign-component-content-card-shadow-color: rgba(27, 28, 29, 0.04);
+
+ /* Status pills, fixed for the four school sets: received is the
+ * primary's own tint. info 8.73:1, success 5.77:1, warning 6.53:1, error 7.22:1. */
+ --nldesign-component-status-badge-info-background-color: #E8F1EB;
+ --nldesign-component-status-badge-info-color: #1F4A33;
+ --nldesign-component-status-badge-success-background-color: #E7F3EA;
+ --nldesign-component-status-badge-success-color: #1E6B2A;
+ --nldesign-component-status-badge-warning-background-color: #FFF4DE;
+ --nldesign-component-status-badge-warning-color: #7A4F00;
+ --nldesign-component-status-badge-error-background-color: #FCEDEC;
+ --nldesign-component-status-badge-error-color: #A30000;
+
+ /* The login watermark: the emblem in grey, large and faint, in the bottom
+ * corner of the login page while the workplace layout is light. */
+ --nldesign-login-watermark-image: url('../../img/logos/wilgenboom-emblem-grey.svg');
+
+ /* The motif, "de twijgen": the hanging twigs of the willow, short bars with round ends in uneven lengths (14, 8, 11, 6, 12, 9, 5, 13, 7 and 10px, 6px wide, 6px apart), green with every seventh one yellow. Drawn
+ * along the top bar and the login card while the brand stripe is on.
+ * The three colours read the twigs as proportions for the component library, which draws flat bands only: green, yellow, green in the ratio 3 : 1 : 3, one bar in seven. */
+ --nldesign-brand-stripe-color-1: #2F6B4A;
+ --nldesign-brand-stripe-color-2: #F5B82E;
+ --nldesign-brand-stripe-color-3: #2F6B4A;
+ --nldesign-brand-stripe-ratio-1: 3;
+ --nldesign-brand-stripe-ratio-2: 1;
+ --nldesign-brand-stripe-ratio-3: 3;
+ --nldesign-brand-stripe-height: 14px;
+ --nldesign-brand-stripe-image: url("data:image/svg+xml,");
+}
diff --git a/docs/features/public-portals-as-consumers.md b/docs/features/public-portals-as-consumers.md
index 0ab322655..b72abb817 100644
--- a/docs/features/public-portals-as-consumers.md
+++ b/docs/features/public-portals-as-consumers.md
@@ -46,12 +46,12 @@ to travel through that bridge, or it reaches nothing.
**Portaliq does not link it yet.** Its open change `site-links-the-theme-bridge`
adds the link. Until then a portal paints from whatever the set itself declares.
-Measured coverage of the listed sets (`token-sets.json`, 59 sets):
+Measured coverage of the listed sets (`token-sets.json`, 63 sets):
| What a set declares | Sets |
| --- | --- |
| the full `--utrecht-*` role layer | 26 |
-| only `--nldesign-*` | 11 |
+| only `--nldesign-*` | 15 |
| Den Haag component properties | 18 |
| a case card property | 2 |
diff --git a/docs/reference/brand-identity.md b/docs/reference/brand-identity.md
index ccad5d972..16e3e4ffe 100644
--- a/docs/reference/brand-identity.md
+++ b/docs/reference/brand-identity.md
@@ -50,6 +50,10 @@ Colors are sourced from each organization's official NL Design System token set.
| Gemeente Rotterdam |  `#00811f` | `#FFFFFF` | `rotterdam.svg` |
| xxllnc |  `#333333` | `#FFFFFF` | `xxllnc.svg` |
| `zuiddrecht.svg`, `zuiddrecht-dark.svg`, `zuiddrecht-emblem.svg`, `zuiddrecht-emblem-grey.svg` | Conduction's own design for the demo municipality Zuiddrecht, which does not exist |
+| `wilgenboom.svg`, `wilgenboom-dark.svg`, `wilgenboom-emblem.svg`, `wilgenboom-emblem-grey.svg` | Conduction's own design for Basisschool De Wilgenboom, a demo school in Zuiddrecht, which does not exist |
+| `vaartveld.svg`, `vaartveld-dark.svg`, `vaartveld-emblem.svg`, `vaartveld-emblem-grey.svg` | Conduction's own design for Vaartveld College, a demo school in Zuiddrecht, which does not exist |
+| `esdoornveen.svg`, `esdoornveen-dark.svg`, `esdoornveen-emblem.svg`, `esdoornveen-emblem-grey.svg` | Conduction's own design for Esdoornveen, mbo college, a demo school in Zuiddrecht, which does not exist |
+| `warmtepompacademie.svg`, `warmtepompacademie-dark.svg`, `warmtepompacademie-emblem.svg`, `warmtepompacademie-emblem-grey.svg` | Conduction's own design for Warmtepompacademie, a demo school in Zuiddrecht, which does not exist |
| Gemeente Zevenaar |  `#596E28` | `#FFFFFF` | -- |
| Gemeente Zwolle |  `#3A4F93` | `#FFFFFF` | -- |
| (EXAMPLE) Basisschool |  `#B03A12` | `#FFFFFF` | `example-basisschool.svg` |
@@ -58,6 +62,10 @@ Colors are sourced from each organization's official NL Design System token set.
| (EXAMPLE) Opleider |  `#0E4D5C` | `#FFFFFF` | `example-opleider.svg` |
| (EXAMPLE) Gemeente |  `#12506B` | `#FFFFFF` | `example-gemeente.svg` |
| Gemeente Zuiddrecht (demo) |  `#3669A5` | `#F5F6F8` | `zuiddrecht.svg`, `zuiddrecht-dark.svg` |
+| Basisschool De Wilgenboom (demo) |  `#2F6B4A` | `#F5F6F8` | `wilgenboom.svg`, `wilgenboom-dark.svg` |
+| Vaartveld College (demo) |  `#1F4FD8` | `#F5F6F8` | `vaartveld.svg`, `vaartveld-dark.svg` |
+| Esdoornveen, mbo college (demo) |  `#5B2E91` | `#F5F6F8` | `esdoornveen.svg`, `esdoornveen-dark.svg` |
+| Warmtepompacademie (demo) |  `#0B6E7A` | `#F5F6F8` | `warmtepompacademie.svg`, `warmtepompacademie-dark.svg` |
## Logo Sources
diff --git a/docs/reference/contrast-report.json b/docs/reference/contrast-report.json
index eaba36b1c..f2976b055 100644
--- a/docs/reference/contrast-report.json
+++ b/docs/reference/contrast-report.json
@@ -116,6 +116,13 @@
"textThreshold": 4.5,
"uiThreshold": 3.0
},
+ "esdoornveen": {
+ "verdict": "pass",
+ "textRatio": 9.36,
+ "uiRatio": 8.65,
+ "textThreshold": 4.5,
+ "uiThreshold": 3.0
+ },
"example-basisschool": {
"verdict": "pass",
"textRatio": 6.07,
@@ -354,6 +361,13 @@
"textThreshold": 4.5,
"uiThreshold": 3.0
},
+ "vaartveld": {
+ "verdict": "pass",
+ "textRatio": 6.63,
+ "uiRatio": 6.13,
+ "textThreshold": 4.5,
+ "uiThreshold": 3.0
+ },
"venray": {
"verdict": "pass",
"textRatio": 4.94,
@@ -375,6 +389,13 @@
"textThreshold": 4.5,
"uiThreshold": 3.0
},
+ "warmtepompacademie": {
+ "verdict": "pass",
+ "textRatio": 5.96,
+ "uiRatio": 5.51,
+ "textThreshold": 4.5,
+ "uiThreshold": 3.0
+ },
"westervoort": {
"verdict": "pass",
"textRatio": 11.3,
@@ -382,6 +403,13 @@
"textThreshold": 4.5,
"uiThreshold": 3.0
},
+ "wilgenboom": {
+ "verdict": "pass",
+ "textRatio": 6.32,
+ "uiRatio": 5.84,
+ "textThreshold": 4.5,
+ "uiThreshold": 3.0
+ },
"xxllnc": {
"verdict": "pass",
"textRatio": 11.24,
diff --git a/docs/reference/contrast-report.md b/docs/reference/contrast-report.md
index b9f7e44dd..2cc5f0dd1 100644
--- a/docs/reference/contrast-report.md
+++ b/docs/reference/contrast-report.md
@@ -34,6 +34,7 @@ system reads `--nldesign-*` tokens, computed by `ContrastService` over
| enkhuizen | 7.23:1 | 4.5:1 | 7.23:1 | 3.0:1 | pass |
| enschede | 4.88:1 | 4.5:1 | 4.88:1 | 3.0:1 | pass |
| epe | 7.60:1 | 4.5:1 | 7.60:1 | 3.0:1 | pass |
+| esdoornveen | 9.36:1 | 4.5:1 | 8.65:1 | 3.0:1 | pass |
| example-basisschool | 6.07:1 | 4.5:1 | 6.07:1 | 3.0:1 | pass |
| example-college | 9.34:1 | 4.5:1 | 9.34:1 | 3.0:1 | pass |
| example-gemeente | 8.80:1 | 4.5:1 | 8.80:1 | 3.0:1 | pass |
@@ -68,10 +69,13 @@ system reads `--nldesign-*` tokens, computed by `ContrastService` over
| tilburg | 12.61:1 | 4.5:1 | 12.61:1 | 3.0:1 | pass |
| tubbergen | 5.91:1 | 4.5:1 | 5.91:1 | 3.0:1 | pass |
| utrecht | 7.41:1 | 4.5:1 | 7.41:1 | 3.0:1 | pass |
+| vaartveld | 6.63:1 | 4.5:1 | 6.13:1 | 3.0:1 | pass |
| venray | 4.94:1 | 4.5:1 | 4.94:1 | 3.0:1 | pass |
| vng | 11.98:1 | 4.5:1 | 11.98:1 | 3.0:1 | pass |
| vught | 4.62:1 | 4.5:1 | 4.55:1 | 3.0:1 | pass |
+| warmtepompacademie | 5.96:1 | 4.5:1 | 5.51:1 | 3.0:1 | pass |
| westervoort | 11.30:1 | 4.5:1 | 11.30:1 | 3.0:1 | pass |
+| wilgenboom | 6.32:1 | 4.5:1 | 5.84:1 | 3.0:1 | pass |
| xxllnc | 11.24:1 | 4.5:1 | 14.16:1 | 3.0:1 | pass |
| zaanstad | 5.23:1 | 4.5:1 | 5.23:1 | 3.0:1 | pass |
| zevenaar | 5.70:1 | 4.5:1 | 5.70:1 | 3.0:1 | pass |
@@ -105,6 +109,7 @@ Pairs: step-current, step-checked, step-not-checked, case-title, case-subtitle,
| enkhuizen | 15 | 0 | 0 | |
| enschede | 15 | 0 | 0 | |
| epe | 15 | 0 | 0 | |
+| esdoornveen | 15 | 0 | 0 | |
| example-basisschool | 15 | 0 | 0 | |
| example-college | 15 | 0 | 0 | |
| example-gemeente | 15 | 0 | 0 | |
@@ -139,10 +144,13 @@ Pairs: step-current, step-checked, step-not-checked, case-title, case-subtitle,
| tilburg | 15 | 0 | 0 | |
| tubbergen | 15 | 0 | 0 | |
| utrecht | 15 | 0 | 0 | |
+| vaartveld | 15 | 0 | 0 | |
| venray | 15 | 0 | 0 | |
| vng | 15 | 0 | 0 | |
| vught | 15 | 0 | 0 | |
+| warmtepompacademie | 15 | 0 | 0 | |
| westervoort | 15 | 0 | 0 | |
+| wilgenboom | 15 | 0 | 0 | |
| xxllnc | 15 | 0 | 0 | |
| zaanstad | 15 | 0 | 0 | |
| zevenaar | 15 | 0 | 0 | |
diff --git a/docs/reference/icons.md b/docs/reference/icons.md
index 44777ddc1..1a97a3ce9 100644
--- a/docs/reference/icons.md
+++ b/docs/reference/icons.md
@@ -127,7 +127,7 @@ release** — do not build new integrations against them; migrate to the set-pre
## Logos
-The 41 logos in `img/logos/` cover government and municipal organizations, plus five fictional example sets and the demo municipality Zuiddrecht. A representative sample:
+The 57 logos in `img/logos/` cover government and municipal organizations, plus five fictional example sets, the demo municipality Zuiddrecht and its four demo schools. A representative sample:
- `amsterdam.svg` - City of Amsterdam logo
- `ggd-amsterdam.svg` - GGD Amsterdam logo
- `stadsarchief.svg` - Amsterdam City Archives
diff --git a/docs/reference/token-set-coverage.md b/docs/reference/token-set-coverage.md
index 73c8b105c..0125e6029 100644
--- a/docs/reference/token-set-coverage.md
+++ b/docs/reference/token-set-coverage.md
@@ -47,6 +47,7 @@ that lowers the allow-list count with nothing fixed, so it has to be written dow
| enkhuizen | 19/87 | system | no (known) | pass |
| enschede | 55/87 | self-hosted | no (known) | pass |
| epe | 0/87 | self-hosted | yes | pass |
+| esdoornveen | 0/87 | self-hosted | yes | pass |
| example-basisschool | 74/87 | self-hosted | yes | pass |
| example-college | 74/87 | self-hosted | yes | pass |
| example-gemeente | 74/87 | self-hosted | yes | pass |
@@ -80,19 +81,22 @@ that lowers the allow-list count with nothing fixed, so it has to be written dow
| tilburg | 25/87 | system | yes | pass |
| tubbergen | 53/87 | self-hosted | no (known) | pass |
| utrecht | 0/87 | self-hosted | yes | pass |
+| vaartveld | 0/87 | self-hosted | yes | pass |
| venray | 23/87 | declared | no (known) | pass |
| vng | 74/87 | declared | yes | pass |
| vught | 23/87 | declared | no (known) | pass |
+| warmtepompacademie | 0/87 | self-hosted | yes | pass |
| westervoort | 8/87 | self-hosted | no (known) | pass |
+| wilgenboom | 0/87 | self-hosted | yes | pass |
| xxllnc | 46/87 | declared | yes | pass |
| zaanstad | 55/87 | self-hosted | no (known) | pass |
| zevenaar | 8/87 | self-hosted | no (known) | pass |
| zuiddrecht | 0/87 | self-hosted | yes | pass |
| zwolle | 0/87 | declared | no (known) | pass |
-- 57 sets measured; 23 pass every gated dimension (font, logo, contrast).
-- bridge (measured, NOT gated): 8 of 53 bridged sets declare none of the 87 --utrecht-* names; median 21.
-- font: 17 declared, 36 self-hosted, 4 system.
-- logo: 34 of 57 point Nextcloud at no logo.
-- contrast: 0 of 57 do not pass.
+- 61 sets measured; 27 pass every gated dimension (font, logo, contrast).
+- bridge (measured, NOT gated): 12 of 57 bridged sets declare none of the 87 --utrecht-* names; median 21.
+- font: 17 declared, 40 self-hosted, 4 system.
+- logo: 34 of 61 point Nextcloud at no logo.
+- contrast: 0 of 61 do not pass.
diff --git a/docs/reference/token-sets/esdoornveen.md b/docs/reference/token-sets/esdoornveen.md
new file mode 100644
index 000000000..e5b926b46
--- /dev/null
+++ b/docs/reference/token-sets/esdoornveen.md
@@ -0,0 +1,302 @@
+
+
+# Esdoornveen, mbo college
+
+Token set `esdoornveen`: 79 declared by this set, 129 from the defaults layer.
+
+Contrast: primary text on primary 9.36:1, primary on background 8.65:1 (pass).
+
+## Colours (Kleuren)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-color-background-dark` |  `#EDEFF2` |  `#1d2026` | this set | Background dark, Table header background |
+| `--nldesign-color-background-darker` |  `#D3D8DF` |  `#2d333c` | this set | Background darker |
+| `--nldesign-color-background-hover` |  `#F0F1F3` |  `#1d1f23` | this set | Main background color |
+| `--nldesign-color-border` |  `#E4E6EA` |  `#24272d` | this set | Border color, Select border, Table row rule, Text input border, `--nldesign-component-separator-border-color` |
+| `--nldesign-color-border-dark` |  `#8A929E` |  `#656c78` | this set | Border dark, Border max contrast |
+| `--nldesign-color-button-primary-background` |  `#5B2E91` |  `#966bc9` | this set | |
+| `--nldesign-color-button-primary-border` |  `#5B2E91` |  `#966bc9` | this set | |
+| `--nldesign-color-button-primary-hover` |  `#43206E` |  `#ab87d7` | this set | |
+| `--nldesign-color-button-primary-text` |  `#ffffff` |  `#111111` | this set | |
+| `--nldesign-color-error` |  `#B30000` |  `#f54949` | this set | Border error, Element error, Error color, Text error, Text input invalid |
+| `--nldesign-color-error-hover` |  `#A30000` |  `#f65656` | this set | Error hover |
+| `--nldesign-color-error-rgb` | `179, 0, 0` | `245, 73, 73` | this set | Error text color |
+| `--nldesign-color-favorite` |  `#e17000` |  `#f48c25` | defaults | Background blur filter |
+| `--nldesign-color-focus` |  `rgba(91, 46, 145, 0.5)` |  `#966bc980` | this set | Button focus ring |
+| `--nldesign-color-focus-rgb` | `91, 46, 145` | `150, 107, 201` | this set | |
+| `--nldesign-color-header-background` |  `#ffffff` |  `#141414` | this set | |
+| `--nldesign-color-header-text` |  `#1B1C1D` |  `#e2e3e4` | this set | |
+| `--nldesign-color-info` |  `#5B2E91` |  `#966bc9` | this set | Info color, Info hover color, Text input focus |
+| `--nldesign-color-info-rgb` | `91, 46, 145` | `150, 107, 201` | this set | |
+| `--nldesign-color-link` |  `#5B2E91` |  `#d8c8eb` | this set | Link colour |
+| `--nldesign-color-link-hover` |  `#43206E` |  `#ab87d7` | this set | Link hover colour |
+| `--nldesign-color-link-visited` |  `#42145f` |  `#c392e3` | defaults | `--nldesign-component-link-visited-color` |
+| `--nldesign-color-logo-background` | `transparent` | | defaults | |
+| `--nldesign-color-nav-background` |  `#ffffff` |  `#141414` | this set | |
+| `--nldesign-color-placeholder-dark` |  `#cccccc` |  `#3f3f3f` | defaults | Placeholder dark |
+| `--nldesign-color-placeholder-light` |  `#e5e5e5` |  `#2a2a2a` | defaults | Placeholder light |
+| `--nldesign-color-primary` |  `#5B2E91` |  `#decff0` | this set | Badge background, Primary button background, Primary color, Primary element color, Primary element light text and 7 more |
+| `--nldesign-color-primary-hover` |  `#43206E` |  `#43206e` | this set | Primary button hover, Primary element hover, Primary hover color |
+| `--nldesign-color-primary-light` |  `#F0EAF7` |  `#20132e` | this set | Primary element light, Tertiary button hover, `--color-primary-element-text-dark` |
+| `--nldesign-color-primary-light-hover` |  `#E6DDF0` |  `#281b37` | this set | Primary element light hover, Primary light hover, Tertiary button pressed |
+| `--nldesign-color-primary-text` |  `#ffffff` |  `#111111` | this set | Badge number, Primary button label, Primary element text, Primary text color |
+| `--nldesign-color-success` |  `#1E6B2A` |  `#8ad896` | this set | Border success, Element success, Success color, Text success |
+| `--nldesign-color-success-rgb` | `30, 107, 42` | `138, 216, 150` | this set | Success hover color |
+| `--nldesign-color-text` |  `#1B1C1D` |  `#e2e3e4` | this set | Body text colour, Main text color, Table header label, `--nldesign-component-form-field-label-color`, `--nldesign-component-heading-1-color` and 8 more |
+| `--nldesign-color-text-light` |  `#ffffff` |  `#9e9e9e` | this set | Muted text default color |
+| `--nldesign-color-text-muted` |  `#5E6168` |  `#999ca3` | this set | Text lighter, Text max contrast |
+| `--nldesign-color-warning` |  `#7A4F00` |  `#f8ca77` | this set | Element warning, Text warning, Warning color |
+| `--nldesign-color-warning-rgb` | `122, 79, 0` | `248, 202, 119` | this set | Warning hover color |
+| `--nldesign-component-badge-background-color` | `var(
+ --nldesign-color-primary
+ )` |  `#966bc9` | defaults | |
+| `--nldesign-component-badge-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#111111` | defaults | |
+| `--nldesign-component-button-active-background-color` | `var(
+ --nldesign-color-primary-light-hover
+ )` |  `#281b37` | defaults | |
+| `--nldesign-component-button-active-color` | `var(
+ --nldesign-color-primary
+ )` |  `#9b6ed1` | defaults | |
+| `--nldesign-component-button-background-color` | `transparent` | | defaults | |
+| `--nldesign-component-button-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#966bc9` | defaults | |
+| `--nldesign-component-button-color` | `var(--nldesign-color-primary)` |  `#9b6ed1` | defaults | |
+| `--nldesign-component-button-disabled-background-color` |  `#e5e5e5` |  `#2a2a2a` | defaults | |
+| `--nldesign-component-button-disabled-border-color` |  `#b4b4b4` |  `#535353` | defaults | |
+| `--nldesign-component-button-disabled-color` |  `#696969` |  `#9e9e9e` | defaults | |
+| `--nldesign-component-button-focus-border-color` | `var(
+ --nldesign-color-focus
+ )` |  `#966bc980` | defaults | |
+| `--nldesign-component-button-hover-background-color` | `var(
+ --nldesign-color-primary-light
+ )` |  `#20132e` | defaults | |
+| `--nldesign-component-button-hover-border-color` | `var(
+ --nldesign-color-primary-hover
+ )` |  `#ab87d7` | defaults | |
+| `--nldesign-component-button-hover-color` | `var(
+ --nldesign-color-primary
+ )` |  `#9b6ed1` | defaults | |
+| `--nldesign-component-button-primary-action-background-color` | `var(
+ --nldesign-color-primary
+ )` |  `#966bc9` | defaults | |
+| `--nldesign-component-button-primary-action-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#966bc9` | defaults | |
+| `--nldesign-component-button-primary-action-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#111111` | defaults | |
+| `--nldesign-component-button-primary-action-hover-background-color` | `var(
+ --nldesign-color-primary-hover
+ )` |  `#ab87d7` | defaults | |
+| `--nldesign-component-button-primary-action-hover-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#2e2e2e` | defaults | |
+| `--nldesign-component-button-secondary-action-background-color` | `transparent` | | defaults | |
+| `--nldesign-component-button-secondary-action-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#966bc9` | defaults | |
+| `--nldesign-component-button-secondary-action-color` | `var(
+ --nldesign-color-primary
+ )` |  `#9b6ed1` | defaults | |
+| `--nldesign-component-button-secondary-action-hover-background-color` | `var(
+ --nldesign-color-primary-light
+ )` |  `#20132e` | defaults | |
+| `--nldesign-component-form-field-label-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-form-fieldset-border-color` | `var(
+ --nldesign-color-border
+ )` |  `#24272d` | defaults | |
+| `--nldesign-component-form-select-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-form-select-focus-border-color` | `var(--nldesign-color-info)` |  `#966bc9` | defaults | |
+| `--nldesign-component-heading-1-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-2-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-3-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-4-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-5-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-6-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-link-color` | `var(--nldesign-color-link)` |  `#9b6ed1` | defaults | |
+| `--nldesign-component-link-hover-color` | `var(--nldesign-color-link-hover)` |  `#b491df` | defaults | |
+| `--nldesign-component-link-visited-color` | `var(--nldesign-color-link-visited)` |  `#cea0eb` | defaults | |
+| `--nldesign-component-ordered-list-color` | `var(
+ --nldesign-color-text
+ )` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-paragraph-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-separator-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-table-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-table-header-background-color` | `var(
+ --nldesign-color-background-dark
+ )` |  `#1d2026` | defaults | |
+| `--nldesign-component-table-header-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-table-row-hover-background-color` | `var(
+ --nldesign-color-background-hover
+ )` |  `#1d1f23` | defaults | |
+| `--nldesign-component-textbox-background-color` |  `#ffffff` |  `#141414` | defaults | |
+| `--nldesign-component-textbox-border-color` | `var(--nldesign-color-border)` |  `#5d6474` | defaults | |
+| `--nldesign-component-textbox-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-textbox-disabled-background-color` |  `#e5e5e5` |  `#2a2a2a` | defaults | |
+| `--nldesign-component-textbox-disabled-color` |  `#696969` |  `#9e9e9e` | defaults | |
+| `--nldesign-component-textbox-focus-border-color` | `var(--nldesign-color-info)` |  `#966bc9` | defaults | |
+| `--nldesign-component-textbox-hover-border-color` | `var(
+ --nldesign-color-border-dark
+ )` |  `#656c78` | defaults | |
+| `--nldesign-component-textbox-invalid-border-color` | `var(--nldesign-color-error)` |  `#f54949` | defaults | |
+| `--nldesign-component-unordered-list-color` | `var(
+ --nldesign-color-text
+ )` |  `#e2e3e4` | defaults | |
+
+## Typography (Typografie)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-component-badge-font-size` | `0.875rem` | | defaults | |
+| `--nldesign-component-badge-font-weight` | `700` | | defaults | |
+| `--nldesign-component-button-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-button-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-button-font-weight` | `700` | | defaults | |
+| `--nldesign-component-form-field-label-font-weight` | `700` | | defaults | |
+| `--nldesign-component-heading-1-font-size` | `2.5rem` | | defaults | |
+| `--nldesign-component-heading-1-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-1-line-height` | `1.2` | | defaults | |
+| `--nldesign-component-heading-2-font-size` | `2rem` | | defaults | |
+| `--nldesign-component-heading-2-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-2-line-height` | `1.25` | | defaults | |
+| `--nldesign-component-heading-3-font-size` | `1.5rem` | | defaults | |
+| `--nldesign-component-heading-3-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-3-line-height` | `1.3` | | defaults | |
+| `--nldesign-component-heading-4-font-size` | `1.25rem` | | defaults | |
+| `--nldesign-component-heading-4-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-4-line-height` | `1.35` | | defaults | |
+| `--nldesign-component-heading-5-font-size` | `1.125rem` | | defaults | |
+| `--nldesign-component-heading-5-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-5-line-height` | `1.4` | | defaults | |
+| `--nldesign-component-heading-6-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-heading-6-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-6-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-heading-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-heading-font-weight` | `var(--nldesign-font-weight-heading)` | | defaults | |
+| `--nldesign-component-link-font-weight` | `var(
+ --nldesign-font-weight-default
+ )` | | defaults | |
+| `--nldesign-component-link-text-decoration` | `underline` | | defaults | |
+| `--nldesign-component-ordered-list-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-ordered-list-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-paragraph-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-paragraph-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-paragraph-font-weight` | `var(--nldesign-font-weight-default)` | | defaults | |
+| `--nldesign-component-paragraph-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-table-header-font-weight` | `700` | | defaults | |
+| `--nldesign-component-textbox-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-textbox-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-unordered-list-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-unordered-list-line-height` | `1.5` | | defaults | |
+| `--nldesign-font-family` | `'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif` | | this set | Font family, `--nldesign-component-button-font-family`, `--nldesign-component-textbox-font-family` |
+| `--nldesign-font-weight-default` | `400` | | defaults | Base font size |
+| `--nldesign-font-weight-element` | `500` | | defaults | Control font weight |
+| `--nldesign-font-weight-heading` | `700` | | defaults | Heading font weight |
+
+## Spacing and shape (Ruimte en vorm)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-border-radius` | `8px` | | this set | Border radius element, Button corner, Input border width, Select corner, Text input corner |
+| `--nldesign-border-radius-large` | `12px` | | this set | Container radius |
+| `--nldesign-border-radius-pill` | `100px` | | this set | Badge shape, Border radius pill |
+| `--nldesign-border-radius-rounded` | `28px` | | this set | Border radius rounded |
+| `--nldesign-border-radius-small` | `4px` | | this set | Border radius small |
+| `--nldesign-component-badge-border-radius` | `var(
+ --nldesign-border-radius-pill
+ )` | | defaults | |
+| `--nldesign-component-badge-padding-block` | `0.125rem` | | defaults | |
+| `--nldesign-component-badge-padding-inline` | `0.5rem` | | defaults | |
+| `--nldesign-component-button-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-button-border-width` | `1px` | | defaults | |
+| `--nldesign-component-button-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-button-padding-inline` | `1rem` | | defaults | |
+| `--nldesign-component-form-fieldset-border-width` | `1px` | | defaults | |
+| `--nldesign-component-form-select-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-separator-border-width` | `1px` | | defaults | |
+| `--nldesign-component-table-border-width` | `1px` | | defaults | |
+| `--nldesign-component-table-cell-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-table-cell-padding-inline` | `0.75rem` | | defaults | |
+| `--nldesign-component-textbox-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-textbox-border-width` | `1px` | | defaults | |
+| `--nldesign-component-textbox-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-textbox-padding-inline` | `0.75rem` | | defaults | |
+| `--nldesign-header-border-bottom` | `1px solid rgba(138, 146, 158, 0.25)` | | this set | |
+| `--nldesign-logo-height` | `auto` | | defaults | |
+| `--nldesign-logo-width` | `127px` | | this set | |
+| `--nldesign-size-lint` | `0px` | | defaults | |
+| `--nldesign-size-lint-height` | `0px` | | defaults | |
+
+## Other tokens (Overige tokens)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-animation-easing` | `ease` | | defaults | |
+| `--nldesign-animation-quick` | `100ms` | | defaults | Header menu item height |
+| `--nldesign-animation-slow` | `300ms` | | defaults | Animation slow |
+| `--nldesign-header-icon-filter` | `invert(1) brightness(0) contrast(100)` | | defaults | |
+| `--nldesign-logo-bottom` | `1px` | | defaults | |
+| `--nldesign-logo-center` | `50%` | | defaults | |
+| `--nldesign-logo-filter` | `none` | | defaults | |
+| `--nldesign-logo-inset` | `12px` | | defaults | |
+| `--nldesign-logo-top` | `1px` | | defaults | |
+
+## Tokens nothing reads (Tokens die niets leest)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--esdoornveen-color-accent` |  `#C2255C` |  `#d14274` | this set | |
+| `--esdoornveen-color-accent-light` |  `#FBE9F0` |  `#330c1b` | this set | |
+| `--esdoornveen-color-accent-text` |  `#9C1C49` |  `#e36390` | this set | |
+| `--esdoornveen-color-ink` |  `#1B1C1D` |  `#d2d3d4` | this set | |
+| `--esdoornveen-color-line` |  `#E4E6EA` |  `#24272d` | this set | |
+| `--esdoornveen-color-main` |  `#5B2E91` |  `#966bc9` | this set | |
+| `--esdoornveen-color-main-deep` |  `#43206E` |  `#ab87d7` | this set | |
+| `--esdoornveen-color-main-light` |  `#F0EAF7` |  `#20132e` | this set | |
+| `--esdoornveen-color-muted` |  `#5E6168` |  `#93969c` | this set | |
+| `--esdoornveen-color-surface` |  `#F5F6F8` |  `#171a20` | this set | |
+| `--esdoornveen-font-family-code` | `'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace` | | this set | |
+| `--nldesign-brand-stripe-color-1` |  `#5B2E91` |  `#966bc9` | this set | |
+| `--nldesign-brand-stripe-color-2` |  `#C2255C` |  `#d14274` | this set | |
+| `--nldesign-brand-stripe-color-3` |  `#5B2E91` |  `#966bc9` | this set | |
+| `--nldesign-brand-stripe-height` | `6px` | | this set | |
+| `--nldesign-brand-stripe-image` | `linear-gradient(122deg, #5B2E91 0 28.73px, #C2255C 28.73px 110.13px, #5B2E91 110.13px)` | | this set | |
+| `--nldesign-brand-stripe-ratio-1` | `1` | | this set | |
+| `--nldesign-brand-stripe-ratio-2` | `3` | | this set | |
+| `--nldesign-brand-stripe-ratio-3` | `10` | | this set | |
+| `--nldesign-component-content-card-shadow-color` |  `rgba(27, 28, 29, 0.04)` |  `#d2d3d40a` | this set | |
+| `--nldesign-component-content-surface-background-color` |  `#F5F6F8` |  `#171a20` | this set | |
+| `--nldesign-component-navigation-active-background-color` |  `#C2255C` |  `#d14274` | this set | |
+| `--nldesign-component-navigation-active-color` |  `#9C1C49` |  `#e36390` | this set | |
+| `--nldesign-component-navigation-badge-background-color` |  `#C2255C` |  `#d14274` | this set | |
+| `--nldesign-component-navigation-badge-color` |  `#ffffff` |  `#000000` | this set | |
+| `--nldesign-component-status-badge-error-background-color` |  `#FCEDEC` |  `#310d0a` | this set | |
+| `--nldesign-component-status-badge-error-color` |  `#A30000` |  `#ff5c5c` | this set | |
+| `--nldesign-component-status-badge-info-background-color` |  `#F0EAF7` |  `#20132e` | this set | |
+| `--nldesign-component-status-badge-info-color` |  `#43206E` |  `#b491df` | this set | |
+| `--nldesign-component-status-badge-success-background-color` |  `#E7F3EA` |  `#192e1e` | this set | |
+| `--nldesign-component-status-badge-success-color` |  `#1E6B2A` |  `#94e1a0` | this set | |
+| `--nldesign-component-status-badge-warning-background-color` |  `#FFF4DE` |  `#412d03` | this set | |
+| `--nldesign-component-status-badge-warning-color` |  `#7A4F00` |  `#ffd485` | this set | |
+| `--nldesign-login-watermark-image` | `url('../../img/logos/esdoornveen-emblem-grey.svg')` | | this set | |
+| `--nldesign-login-watermark-opacity` | `0.06` | | this set | |
+| `--nldesign-logo-url` | `url('../../img/logos/esdoornveen.svg')` | `url('../../../img/logos/esdoornveen-dark.svg')` | this set | |
+| `--nldesign-website-border-radius` | `4px` | | this set | |
+| `--nldesign-website-border-radius-large` | `8px` | | this set | |
diff --git a/docs/reference/token-sets/index.md b/docs/reference/token-sets/index.md
index b108eb35f..5ccb01c5f 100644
--- a/docs/reference/token-sets/index.md
+++ b/docs/reference/token-sets/index.md
@@ -19,6 +19,7 @@ The tokens of every shipped token set: the value, the dark-mode value, whether i
- [Gemeente Enkhuizen](./enkhuizen.md) `enkhuizen`
- [Gemeente Enschede](./enschede.md) `enschede`
- [Gemeente Epe](./epe.md) `epe`
+- [Esdoornveen, mbo college](./esdoornveen.md) `esdoornveen`
- [(EXAMPLE) Basisschool](./example-basisschool.md) `example-basisschool`
- [(EXAMPLE) College](./example-college.md) `example-college`
- [(EXAMPLE) Gemeente](./example-gemeente.md) `example-gemeente`
@@ -54,10 +55,13 @@ The tokens of every shipped token set: the value, the dark-mode value, whether i
- [Gemeente Tilburg](./tilburg.md) `tilburg`
- [Gemeente Tubbergen](./tubbergen.md) `tubbergen`
- [Gemeente Utrecht](./utrecht.md) `utrecht`
+- [Vaartveld College](./vaartveld.md) `vaartveld`
- [Gemeente Venray](./venray.md) `venray`
- [VNG Vereniging Nederlandse Gemeenten](./vng.md) `vng`
- [Gemeente Vught](./vught.md) `vught`
+- [Warmtepompacademie](./warmtepompacademie.md) `warmtepompacademie`
- [Gemeente Westervoort](./westervoort.md) `westervoort`
+- [Basisschool De Wilgenboom](./wilgenboom.md) `wilgenboom`
- [xxllnc](./xxllnc.md) `xxllnc`
- [Gemeente Zaanstad](./zaanstad.md) `zaanstad`
- [Gemeente Zevenaar](./zevenaar.md) `zevenaar`
diff --git a/docs/reference/token-sets/vaartveld.md b/docs/reference/token-sets/vaartveld.md
new file mode 100644
index 000000000..5c64328ef
--- /dev/null
+++ b/docs/reference/token-sets/vaartveld.md
@@ -0,0 +1,301 @@
+
+
+# Vaartveld College
+
+Token set `vaartveld`: 79 declared by this set, 128 from the defaults layer.
+
+Contrast: primary text on primary 6.63:1, primary on background 6.13:1 (pass).
+
+## Colours (Kleuren)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-color-background-dark` |  `#EDEFF2` |  `#1d2026` | this set | Background dark, Table header background |
+| `--nldesign-color-background-darker` |  `#D3D8DF` |  `#2d333c` | this set | Background darker |
+| `--nldesign-color-background-hover` |  `#F0F1F3` |  `#1d1f23` | this set | Main background color |
+| `--nldesign-color-border` |  `#E4E6EA` |  `#24272d` | this set | Border color, Select border, Table row rule, Text input border, `--nldesign-component-separator-border-color` |
+| `--nldesign-color-border-dark` |  `#8A929E` |  `#656c78` | this set | Border dark, Border max contrast |
+| `--nldesign-color-button-primary-background` |  `#1F4FD8` |  `#2f5bd7` | this set | |
+| `--nldesign-color-button-primary-border` |  `#1F4FD8` |  `#2f5bd7` | this set | |
+| `--nldesign-color-button-primary-hover` |  `#14338F` |  `#6a88e2` | this set | |
+| `--nldesign-color-button-primary-text` |  `#ffffff` |  `#fefefe` | this set | |
+| `--nldesign-color-error` |  `#B30000` |  `#f54949` | this set | Border error, Element error, Error color, Text error, Text input invalid |
+| `--nldesign-color-error-hover` |  `#A30000` |  `#f65656` | this set | Error hover |
+| `--nldesign-color-error-rgb` | `179, 0, 0` | `245, 73, 73` | this set | Error text color |
+| `--nldesign-color-favorite` |  `#e17000` |  `#f48c25` | defaults | Background blur filter |
+| `--nldesign-color-focus` |  `rgba(31, 79, 216, 0.5)` |  `#2f5bd780` | this set | Button focus ring |
+| `--nldesign-color-focus-rgb` | `31, 79, 216` | `47, 91, 215` | this set | |
+| `--nldesign-color-header-background` |  `#ffffff` |  `#141414` | this set | |
+| `--nldesign-color-header-text` |  `#1B1C1D` |  `#e2e3e4` | this set | |
+| `--nldesign-color-info` |  `#1F4FD8` |  `#2f5bd7` | this set | Info color, Info hover color, Text input focus |
+| `--nldesign-color-info-rgb` | `31, 79, 216` | `47, 91, 215` | this set | |
+| `--nldesign-color-link` |  `#1F4FD8` |  `#9aafec` | this set | Link colour |
+| `--nldesign-color-link-hover` |  `#14338F` |  `#6a88e2` | this set | Link hover colour |
+| `--nldesign-color-link-visited` |  `#42145f` |  `#c392e3` | defaults | `--nldesign-component-link-visited-color` |
+| `--nldesign-color-logo-background` | `transparent` | | defaults | |
+| `--nldesign-color-nav-background` |  `#ffffff` |  `#141414` | this set | |
+| `--nldesign-color-placeholder-dark` |  `#cccccc` |  `#3f3f3f` | defaults | Placeholder dark |
+| `--nldesign-color-placeholder-light` |  `#e5e5e5` |  `#2a2a2a` | defaults | Placeholder light |
+| `--nldesign-color-primary` |  `#1F4FD8` |  `#89a3ee` | this set | Badge background, Primary button background, Primary color, Primary element color, Primary element light text and 7 more |
+| `--nldesign-color-primary-hover` |  `#14338F` |  `#14338f` | this set | Primary button hover, Primary element hover, Primary hover color |
+| `--nldesign-color-primary-light` |  `#E8EEFC` |  `#0a1735` | this set | Primary element light, Tertiary button hover, `--color-primary-element-text-dark` |
+| `--nldesign-color-primary-light-hover` |  `#DAE3F9` |  `#0e1c3f` | this set | Primary element light hover, Primary light hover, Tertiary button pressed |
+| `--nldesign-color-primary-text` |  `#ffffff` |  `#111111` | this set | Badge number, Primary button label, Primary element text, Primary text color |
+| `--nldesign-color-success` |  `#1E6B2A` |  `#8ad896` | this set | Border success, Element success, Success color, Text success |
+| `--nldesign-color-success-rgb` | `30, 107, 42` | `138, 216, 150` | this set | Success hover color |
+| `--nldesign-color-text` |  `#1B1C1D` |  `#e2e3e4` | this set | Body text colour, Main text color, Table header label, `--nldesign-component-form-field-label-color`, `--nldesign-component-heading-1-color` and 8 more |
+| `--nldesign-color-text-light` |  `#ffffff` |  `#9e9e9e` | this set | Muted text default color |
+| `--nldesign-color-text-muted` |  `#5E6168` |  `#999ca3` | this set | Text lighter, Text max contrast |
+| `--nldesign-color-warning` |  `#7A4F00` |  `#f8ca77` | this set | Element warning, Text warning, Warning color |
+| `--nldesign-color-warning-rgb` | `122, 79, 0` | `248, 202, 119` | this set | Warning hover color |
+| `--nldesign-component-badge-background-color` | `var(
+ --nldesign-color-primary
+ )` |  `#2f5bd7` | defaults | |
+| `--nldesign-component-badge-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#fefefe` | defaults | |
+| `--nldesign-component-button-active-background-color` | `var(
+ --nldesign-color-primary-light-hover
+ )` |  `#0e1c3f` | defaults | |
+| `--nldesign-component-button-active-color` | `var(
+ --nldesign-color-primary
+ )` |  `#567be7` | defaults | |
+| `--nldesign-component-button-background-color` | `transparent` | | defaults | |
+| `--nldesign-component-button-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#2f5bd7` | defaults | |
+| `--nldesign-component-button-color` | `var(--nldesign-color-primary)` |  `#567be7` | defaults | |
+| `--nldesign-component-button-disabled-background-color` |  `#e5e5e5` |  `#2a2a2a` | defaults | |
+| `--nldesign-component-button-disabled-border-color` |  `#b4b4b4` |  `#535353` | defaults | |
+| `--nldesign-component-button-disabled-color` |  `#696969` |  `#9e9e9e` | defaults | |
+| `--nldesign-component-button-focus-border-color` | `var(
+ --nldesign-color-focus
+ )` |  `#2f5bd780` | defaults | |
+| `--nldesign-component-button-hover-background-color` | `var(
+ --nldesign-color-primary-light
+ )` |  `#0a1735` | defaults | |
+| `--nldesign-component-button-hover-border-color` | `var(
+ --nldesign-color-primary-hover
+ )` |  `#6a88e2` | defaults | |
+| `--nldesign-component-button-hover-color` | `var(
+ --nldesign-color-primary
+ )` |  `#567be7` | defaults | |
+| `--nldesign-component-button-primary-action-background-color` | `var(
+ --nldesign-color-primary
+ )` |  `#2f5bd7` | defaults | |
+| `--nldesign-component-button-primary-action-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#2f5bd7` | defaults | |
+| `--nldesign-component-button-primary-action-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#fefefe` | defaults | |
+| `--nldesign-component-button-primary-action-hover-background-color` | `var(
+ --nldesign-color-primary-hover
+ )` |  `#6a88e2` | defaults | |
+| `--nldesign-component-button-primary-action-hover-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#222222` | defaults | |
+| `--nldesign-component-button-secondary-action-background-color` | `transparent` | | defaults | |
+| `--nldesign-component-button-secondary-action-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#2f5bd7` | defaults | |
+| `--nldesign-component-button-secondary-action-color` | `var(
+ --nldesign-color-primary
+ )` |  `#c6d2f7` | defaults | |
+| `--nldesign-component-button-secondary-action-hover-background-color` | `var(
+ --nldesign-color-primary-light
+ )` |  `#0a1735` | defaults | |
+| `--nldesign-component-form-field-label-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-form-fieldset-border-color` | `var(
+ --nldesign-color-border
+ )` |  `#24272d` | defaults | |
+| `--nldesign-component-form-select-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-form-select-focus-border-color` | `var(--nldesign-color-info)` |  `#2f5bd7` | defaults | |
+| `--nldesign-component-heading-1-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-2-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-3-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-4-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-5-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-6-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-link-color` | `var(--nldesign-color-link)` |  `#c6d2f7` | defaults | |
+| `--nldesign-component-link-hover-color` | `var(--nldesign-color-link-hover)` |  `#708feb` | defaults | |
+| `--nldesign-component-link-visited-color` | `var(--nldesign-color-link-visited)` |  `#cea0eb` | defaults | |
+| `--nldesign-component-ordered-list-color` | `var(
+ --nldesign-color-text
+ )` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-paragraph-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-separator-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-table-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-table-header-background-color` | `var(
+ --nldesign-color-background-dark
+ )` |  `#1d2026` | defaults | |
+| `--nldesign-component-table-header-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-table-row-hover-background-color` | `var(
+ --nldesign-color-background-hover
+ )` |  `#1d1f23` | defaults | |
+| `--nldesign-component-textbox-background-color` |  `#ffffff` |  `#141414` | defaults | |
+| `--nldesign-component-textbox-border-color` | `var(--nldesign-color-border)` |  `#5d6474` | defaults | |
+| `--nldesign-component-textbox-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-textbox-disabled-background-color` |  `#e5e5e5` |  `#2a2a2a` | defaults | |
+| `--nldesign-component-textbox-disabled-color` |  `#696969` |  `#9e9e9e` | defaults | |
+| `--nldesign-component-textbox-focus-border-color` | `var(--nldesign-color-info)` |  `#2f5bd7` | defaults | |
+| `--nldesign-component-textbox-hover-border-color` | `var(
+ --nldesign-color-border-dark
+ )` |  `#656c78` | defaults | |
+| `--nldesign-component-textbox-invalid-border-color` | `var(--nldesign-color-error)` |  `#f54949` | defaults | |
+| `--nldesign-component-unordered-list-color` | `var(
+ --nldesign-color-text
+ )` |  `#e2e3e4` | defaults | |
+
+## Typography (Typografie)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-component-badge-font-size` | `0.875rem` | | defaults | |
+| `--nldesign-component-badge-font-weight` | `700` | | defaults | |
+| `--nldesign-component-button-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-button-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-button-font-weight` | `700` | | defaults | |
+| `--nldesign-component-form-field-label-font-weight` | `700` | | defaults | |
+| `--nldesign-component-heading-1-font-size` | `2.5rem` | | defaults | |
+| `--nldesign-component-heading-1-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-1-line-height` | `1.2` | | defaults | |
+| `--nldesign-component-heading-2-font-size` | `2rem` | | defaults | |
+| `--nldesign-component-heading-2-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-2-line-height` | `1.25` | | defaults | |
+| `--nldesign-component-heading-3-font-size` | `1.5rem` | | defaults | |
+| `--nldesign-component-heading-3-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-3-line-height` | `1.3` | | defaults | |
+| `--nldesign-component-heading-4-font-size` | `1.25rem` | | defaults | |
+| `--nldesign-component-heading-4-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-4-line-height` | `1.35` | | defaults | |
+| `--nldesign-component-heading-5-font-size` | `1.125rem` | | defaults | |
+| `--nldesign-component-heading-5-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-5-line-height` | `1.4` | | defaults | |
+| `--nldesign-component-heading-6-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-heading-6-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-6-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-heading-font-family` | `'Red Hat Display', 'Red Hat Text', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif` | | this set | |
+| `--nldesign-component-heading-font-weight` | `var(--nldesign-font-weight-heading)` | | defaults | |
+| `--nldesign-component-link-font-weight` | `var(
+ --nldesign-font-weight-default
+ )` | | defaults | |
+| `--nldesign-component-link-text-decoration` | `underline` | | defaults | |
+| `--nldesign-component-ordered-list-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-ordered-list-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-paragraph-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-paragraph-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-paragraph-font-weight` | `var(--nldesign-font-weight-default)` | | defaults | |
+| `--nldesign-component-paragraph-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-table-header-font-weight` | `700` | | defaults | |
+| `--nldesign-component-textbox-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-textbox-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-unordered-list-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-unordered-list-line-height` | `1.5` | | defaults | |
+| `--nldesign-font-family` | `'Red Hat Text', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif` | | this set | Font family, `--nldesign-component-button-font-family`, `--nldesign-component-textbox-font-family` |
+| `--nldesign-font-weight-default` | `400` | | defaults | Base font size |
+| `--nldesign-font-weight-element` | `500` | | defaults | Control font weight |
+| `--nldesign-font-weight-heading` | `700` | | defaults | Heading font weight |
+
+## Spacing and shape (Ruimte en vorm)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-border-radius` | `8px` | | this set | Border radius element, Button corner, Input border width, Select corner, Text input corner |
+| `--nldesign-border-radius-large` | `12px` | | this set | Container radius |
+| `--nldesign-border-radius-pill` | `100px` | | this set | Badge shape, Border radius pill |
+| `--nldesign-border-radius-rounded` | `28px` | | this set | Border radius rounded |
+| `--nldesign-border-radius-small` | `4px` | | this set | Border radius small |
+| `--nldesign-component-badge-border-radius` | `var(
+ --nldesign-border-radius-pill
+ )` | | defaults | |
+| `--nldesign-component-badge-padding-block` | `0.125rem` | | defaults | |
+| `--nldesign-component-badge-padding-inline` | `0.5rem` | | defaults | |
+| `--nldesign-component-button-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-button-border-width` | `1px` | | defaults | |
+| `--nldesign-component-button-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-button-padding-inline` | `1rem` | | defaults | |
+| `--nldesign-component-form-fieldset-border-width` | `1px` | | defaults | |
+| `--nldesign-component-form-select-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-separator-border-width` | `1px` | | defaults | |
+| `--nldesign-component-table-border-width` | `1px` | | defaults | |
+| `--nldesign-component-table-cell-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-table-cell-padding-inline` | `0.75rem` | | defaults | |
+| `--nldesign-component-textbox-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-textbox-border-width` | `1px` | | defaults | |
+| `--nldesign-component-textbox-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-textbox-padding-inline` | `0.75rem` | | defaults | |
+| `--nldesign-header-border-bottom` | `1px solid rgba(138, 146, 158, 0.25)` | | this set | |
+| `--nldesign-logo-height` | `auto` | | defaults | |
+| `--nldesign-logo-width` | `111px` | | this set | |
+| `--nldesign-size-lint` | `0px` | | defaults | |
+| `--nldesign-size-lint-height` | `0px` | | defaults | |
+
+## Other tokens (Overige tokens)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-animation-easing` | `ease` | | defaults | |
+| `--nldesign-animation-quick` | `100ms` | | defaults | Header menu item height |
+| `--nldesign-animation-slow` | `300ms` | | defaults | Animation slow |
+| `--nldesign-header-icon-filter` | `invert(1) brightness(0) contrast(100)` | | defaults | |
+| `--nldesign-logo-bottom` | `1px` | | defaults | |
+| `--nldesign-logo-center` | `50%` | | defaults | |
+| `--nldesign-logo-filter` | `none` | | defaults | |
+| `--nldesign-logo-inset` | `12px` | | defaults | |
+| `--nldesign-logo-top` | `1px` | | defaults | |
+
+## Tokens nothing reads (Tokens die niets leest)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-brand-stripe-color-1` |  `#1F4FD8` |  `#2f5bd7` | this set | |
+| `--nldesign-brand-stripe-color-2` |  `#1FB5A8` |  `#4cd7cb` | this set | |
+| `--nldesign-brand-stripe-color-3` |  `#1F4FD8` |  `#2f5bd7` | this set | |
+| `--nldesign-brand-stripe-height` | `9px` | | this set | |
+| `--nldesign-brand-stripe-image` | `linear-gradient(to bottom, #1F4FD8 0 4px, transparent 4px 7px, #1FB5A8 7px 9px)` | | this set | |
+| `--nldesign-brand-stripe-ratio-1` | `4` | | this set | |
+| `--nldesign-brand-stripe-ratio-2` | `2` | | this set | |
+| `--nldesign-brand-stripe-ratio-3` | `4` | | this set | |
+| `--nldesign-component-content-card-shadow-color` |  `rgba(27, 28, 29, 0.04)` |  `#d2d3d40a` | this set | |
+| `--nldesign-component-content-surface-background-color` |  `#F5F6F8` |  `#171a20` | this set | |
+| `--nldesign-component-navigation-active-background-color` |  `#1FB5A8` |  `#4cd7cb` | this set | |
+| `--nldesign-component-navigation-active-color` |  `#0B6259` |  `#9df4eb` | this set | |
+| `--nldesign-component-navigation-badge-background-color` |  `#1FB5A8` |  `#4cd7cb` | this set | |
+| `--nldesign-component-navigation-badge-color` |  `#1A1A1A` |  `#111111` | this set | |
+| `--nldesign-component-status-badge-error-background-color` |  `#FCEDEC` |  `#310d0a` | this set | |
+| `--nldesign-component-status-badge-error-color` |  `#A30000` |  `#ff5c5c` | this set | |
+| `--nldesign-component-status-badge-info-background-color` |  `#E8EEFC` |  `#0a1735` | this set | |
+| `--nldesign-component-status-badge-info-color` |  `#14338F` |  `#708feb` | this set | |
+| `--nldesign-component-status-badge-success-background-color` |  `#E7F3EA` |  `#192e1e` | this set | |
+| `--nldesign-component-status-badge-success-color` |  `#1E6B2A` |  `#94e1a0` | this set | |
+| `--nldesign-component-status-badge-warning-background-color` |  `#FFF4DE` |  `#412d03` | this set | |
+| `--nldesign-component-status-badge-warning-color` |  `#7A4F00` |  `#ffd485` | this set | |
+| `--nldesign-login-watermark-image` | `url('../../img/logos/vaartveld-emblem-grey.svg')` | | this set | |
+| `--nldesign-login-watermark-opacity` | `0.08` | | this set | |
+| `--nldesign-logo-url` | `url('../../img/logos/vaartveld.svg')` | `url('../../../img/logos/vaartveld-dark.svg')` | this set | |
+| `--nldesign-website-border-radius` | `6px` | | this set | |
+| `--nldesign-website-border-radius-large` | `10px` | | this set | |
+| `--vaartveld-color-accent` |  `#1FB5A8` |  `#4cd7cb` | this set | |
+| `--vaartveld-color-accent-light` |  `#DDF5F2` |  `#143a35` | this set | |
+| `--vaartveld-color-accent-text` |  `#0B6259` |  `#9df4eb` | this set | |
+| `--vaartveld-color-ink` |  `#1B1C1D` |  `#d2d3d4` | this set | |
+| `--vaartveld-color-line` |  `#E4E6EA` |  `#24272d` | this set | |
+| `--vaartveld-color-main` |  `#1F4FD8` |  `#2f5bd7` | this set | |
+| `--vaartveld-color-main-deep` |  `#14338F` |  `#6a88e2` | this set | |
+| `--vaartveld-color-main-light` |  `#E8EEFC` |  `#0a1735` | this set | |
+| `--vaartveld-color-muted` |  `#5E6168` |  `#93969c` | this set | |
+| `--vaartveld-color-surface` |  `#F5F6F8` |  `#171a20` | this set | |
diff --git a/docs/reference/token-sets/warmtepompacademie.md b/docs/reference/token-sets/warmtepompacademie.md
new file mode 100644
index 000000000..c7a5e7ce9
--- /dev/null
+++ b/docs/reference/token-sets/warmtepompacademie.md
@@ -0,0 +1,301 @@
+
+
+# Warmtepompacademie
+
+Token set `warmtepompacademie`: 79 declared by this set, 128 from the defaults layer.
+
+Contrast: primary text on primary 5.96:1, primary on background 5.51:1 (pass).
+
+## Colours (Kleuren)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-color-background-dark` |  `#EDEFF2` |  `#1d2026` | this set | Background dark, Table header background |
+| `--nldesign-color-background-darker` |  `#D3D8DF` |  `#2d333c` | this set | Background darker |
+| `--nldesign-color-background-hover` |  `#F0F1F3` |  `#1d1f23` | this set | Main background color |
+| `--nldesign-color-border` |  `#E4E6EA` |  `#24272d` | this set | Border color, Select border, Table row rule, Text input border, `--nldesign-component-separator-border-color` |
+| `--nldesign-color-border-dark` |  `#8A929E` |  `#656c78` | this set | Border dark, Border max contrast |
+| `--nldesign-color-button-primary-background` |  `#0B6E7A` |  `#79e0ec` | this set | |
+| `--nldesign-color-button-primary-border` |  `#0B6E7A` |  `#79e0ec` | this set | |
+| `--nldesign-color-button-primary-hover` |  `#084F58` |  `#95e6f0` | this set | |
+| `--nldesign-color-button-primary-text` |  `#ffffff` |  `#3e3e3e` | this set | |
+| `--nldesign-color-error` |  `#B30000` |  `#f54949` | this set | Border error, Element error, Error color, Text error, Text input invalid |
+| `--nldesign-color-error-hover` |  `#A30000` |  `#f65656` | this set | Error hover |
+| `--nldesign-color-error-rgb` | `179, 0, 0` | `245, 73, 73` | this set | Error text color |
+| `--nldesign-color-favorite` |  `#e17000` |  `#f48c25` | defaults | Background blur filter |
+| `--nldesign-color-focus` |  `rgba(11, 110, 122, 0.5)` |  `#79e0ec80` | this set | Button focus ring |
+| `--nldesign-color-focus-rgb` | `11, 110, 122` | `121, 224, 236` | this set | |
+| `--nldesign-color-header-background` |  `#ffffff` |  `#141414` | this set | |
+| `--nldesign-color-header-text` |  `#1B1C1D` |  `#e2e3e4` | this set | |
+| `--nldesign-color-info` |  `#0B6E7A` |  `#79e0ec` | this set | Info color, Info hover color, Text input focus |
+| `--nldesign-color-info-rgb` | `11, 110, 122` | `121, 224, 236` | this set | |
+| `--nldesign-color-link` |  `#0B6E7A` |  `#79e0ec` | this set | Link colour |
+| `--nldesign-color-link-hover` |  `#084F58` |  `#95e6f0` | this set | Link hover colour |
+| `--nldesign-color-link-visited` |  `#42145f` |  `#c392e3` | defaults | `--nldesign-component-link-visited-color` |
+| `--nldesign-color-logo-background` | `transparent` | | defaults | |
+| `--nldesign-color-nav-background` |  `#ffffff` |  `#141414` | this set | |
+| `--nldesign-color-placeholder-dark` |  `#cccccc` |  `#3f3f3f` | defaults | Placeholder dark |
+| `--nldesign-color-placeholder-light` |  `#e5e5e5` |  `#2a2a2a` | defaults | Placeholder light |
+| `--nldesign-color-primary` |  `#0B6E7A` |  `#1ad4ea` | this set | Badge background, Primary button background, Primary color, Primary element color, Primary element light text and 7 more |
+| `--nldesign-color-primary-hover` |  `#084F58` |  `#084f58` | this set | Primary button hover, Primary element hover, Primary hover color |
+| `--nldesign-color-primary-light` |  `#E3F1F3` |  `#182f33` | this set | Primary element light, Tertiary button hover, `--color-primary-element-text-dark` |
+| `--nldesign-color-primary-light-hover` |  `#D4E8EB` |  `#1f3a3e` | this set | Primary element light hover, Primary light hover, Tertiary button pressed |
+| `--nldesign-color-primary-text` |  `#ffffff` |  `#111111` | this set | Badge number, Primary button label, Primary element text, Primary text color |
+| `--nldesign-color-success` |  `#1E6B2A` |  `#8ad896` | this set | Border success, Element success, Success color, Text success |
+| `--nldesign-color-success-rgb` | `30, 107, 42` | `138, 216, 150` | this set | Success hover color |
+| `--nldesign-color-text` |  `#1B1C1D` |  `#e2e3e4` | this set | Body text colour, Main text color, Table header label, `--nldesign-component-form-field-label-color`, `--nldesign-component-heading-1-color` and 8 more |
+| `--nldesign-color-text-light` |  `#ffffff` |  `#9e9e9e` | this set | Muted text default color |
+| `--nldesign-color-text-muted` |  `#5E6168` |  `#999ca3` | this set | Text lighter, Text max contrast |
+| `--nldesign-color-warning` |  `#7A4F00` |  `#f8ca77` | this set | Element warning, Text warning, Warning color |
+| `--nldesign-color-warning-rgb` | `122, 79, 0` | `248, 202, 119` | this set | Warning hover color |
+| `--nldesign-component-badge-background-color` | `var(
+ --nldesign-color-primary
+ )` |  `#79e0ec` | defaults | |
+| `--nldesign-component-badge-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#3e3e3e` | defaults | |
+| `--nldesign-component-button-active-background-color` | `var(
+ --nldesign-color-primary-light-hover
+ )` |  `#1f3a3e` | defaults | |
+| `--nldesign-component-button-active-color` | `var(
+ --nldesign-color-primary
+ )` |  `#85e8f4` | defaults | |
+| `--nldesign-component-button-background-color` | `transparent` | | defaults | |
+| `--nldesign-component-button-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#79e0ec` | defaults | |
+| `--nldesign-component-button-color` | `var(--nldesign-color-primary)` |  `#85e8f4` | defaults | |
+| `--nldesign-component-button-disabled-background-color` |  `#e5e5e5` |  `#2a2a2a` | defaults | |
+| `--nldesign-component-button-disabled-border-color` |  `#b4b4b4` |  `#535353` | defaults | |
+| `--nldesign-component-button-disabled-color` |  `#696969` |  `#9e9e9e` | defaults | |
+| `--nldesign-component-button-focus-border-color` | `var(
+ --nldesign-color-focus
+ )` |  `#79e0ec80` | defaults | |
+| `--nldesign-component-button-hover-background-color` | `var(
+ --nldesign-color-primary-light
+ )` |  `#182f33` | defaults | |
+| `--nldesign-component-button-hover-border-color` | `var(
+ --nldesign-color-primary-hover
+ )` |  `#95e6f0` | defaults | |
+| `--nldesign-component-button-hover-color` | `var(
+ --nldesign-color-primary
+ )` |  `#85e8f4` | defaults | |
+| `--nldesign-component-button-primary-action-background-color` | `var(
+ --nldesign-color-primary
+ )` |  `#79e0ec` | defaults | |
+| `--nldesign-component-button-primary-action-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#79e0ec` | defaults | |
+| `--nldesign-component-button-primary-action-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#3e3e3e` | defaults | |
+| `--nldesign-component-button-primary-action-hover-background-color` | `var(
+ --nldesign-color-primary-hover
+ )` |  `#95e6f0` | defaults | |
+| `--nldesign-component-button-primary-action-hover-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#5e5e5e` | defaults | |
+| `--nldesign-component-button-secondary-action-background-color` | `transparent` | | defaults | |
+| `--nldesign-component-button-secondary-action-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#79e0ec` | defaults | |
+| `--nldesign-component-button-secondary-action-color` | `var(
+ --nldesign-color-primary
+ )` |  `#85e8f4` | defaults | |
+| `--nldesign-component-button-secondary-action-hover-background-color` | `var(
+ --nldesign-color-primary-light
+ )` |  `#182f33` | defaults | |
+| `--nldesign-component-form-field-label-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-form-fieldset-border-color` | `var(
+ --nldesign-color-border
+ )` |  `#24272d` | defaults | |
+| `--nldesign-component-form-select-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-form-select-focus-border-color` | `var(--nldesign-color-info)` |  `#79e0ec` | defaults | |
+| `--nldesign-component-heading-1-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-2-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-3-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-4-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-5-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-6-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-link-color` | `var(--nldesign-color-link)` |  `#85e8f4` | defaults | |
+| `--nldesign-component-link-hover-color` | `var(--nldesign-color-link-hover)` |  `#a7eef7` | defaults | |
+| `--nldesign-component-link-visited-color` | `var(--nldesign-color-link-visited)` |  `#cea0eb` | defaults | |
+| `--nldesign-component-ordered-list-color` | `var(
+ --nldesign-color-text
+ )` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-paragraph-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-separator-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-table-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-table-header-background-color` | `var(
+ --nldesign-color-background-dark
+ )` |  `#1d2026` | defaults | |
+| `--nldesign-component-table-header-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-table-row-hover-background-color` | `var(
+ --nldesign-color-background-hover
+ )` |  `#1d1f23` | defaults | |
+| `--nldesign-component-textbox-background-color` |  `#ffffff` |  `#141414` | defaults | |
+| `--nldesign-component-textbox-border-color` | `var(--nldesign-color-border)` |  `#5d6474` | defaults | |
+| `--nldesign-component-textbox-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-textbox-disabled-background-color` |  `#e5e5e5` |  `#2a2a2a` | defaults | |
+| `--nldesign-component-textbox-disabled-color` |  `#696969` |  `#9e9e9e` | defaults | |
+| `--nldesign-component-textbox-focus-border-color` | `var(--nldesign-color-info)` |  `#79e0ec` | defaults | |
+| `--nldesign-component-textbox-hover-border-color` | `var(
+ --nldesign-color-border-dark
+ )` |  `#656c78` | defaults | |
+| `--nldesign-component-textbox-invalid-border-color` | `var(--nldesign-color-error)` |  `#f54949` | defaults | |
+| `--nldesign-component-unordered-list-color` | `var(
+ --nldesign-color-text
+ )` |  `#e2e3e4` | defaults | |
+
+## Typography (Typografie)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-component-badge-font-size` | `0.875rem` | | defaults | |
+| `--nldesign-component-badge-font-weight` | `700` | | defaults | |
+| `--nldesign-component-button-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-button-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-button-font-weight` | `700` | | defaults | |
+| `--nldesign-component-form-field-label-font-weight` | `700` | | defaults | |
+| `--nldesign-component-heading-1-font-size` | `2.5rem` | | defaults | |
+| `--nldesign-component-heading-1-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-1-line-height` | `1.2` | | defaults | |
+| `--nldesign-component-heading-2-font-size` | `2rem` | | defaults | |
+| `--nldesign-component-heading-2-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-2-line-height` | `1.25` | | defaults | |
+| `--nldesign-component-heading-3-font-size` | `1.5rem` | | defaults | |
+| `--nldesign-component-heading-3-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-3-line-height` | `1.3` | | defaults | |
+| `--nldesign-component-heading-4-font-size` | `1.25rem` | | defaults | |
+| `--nldesign-component-heading-4-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-4-line-height` | `1.35` | | defaults | |
+| `--nldesign-component-heading-5-font-size` | `1.125rem` | | defaults | |
+| `--nldesign-component-heading-5-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-5-line-height` | `1.4` | | defaults | |
+| `--nldesign-component-heading-6-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-heading-6-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-6-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-heading-font-family` | `'Barlow Semi Condensed', 'Barlow', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif` | | this set | |
+| `--nldesign-component-heading-font-weight` | `var(--nldesign-font-weight-heading)` | | defaults | |
+| `--nldesign-component-link-font-weight` | `var(
+ --nldesign-font-weight-default
+ )` | | defaults | |
+| `--nldesign-component-link-text-decoration` | `underline` | | defaults | |
+| `--nldesign-component-ordered-list-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-ordered-list-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-paragraph-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-paragraph-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-paragraph-font-weight` | `var(--nldesign-font-weight-default)` | | defaults | |
+| `--nldesign-component-paragraph-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-table-header-font-weight` | `700` | | defaults | |
+| `--nldesign-component-textbox-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-textbox-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-unordered-list-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-unordered-list-line-height` | `1.5` | | defaults | |
+| `--nldesign-font-family` | `'Barlow', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif` | | this set | Font family, `--nldesign-component-button-font-family`, `--nldesign-component-textbox-font-family` |
+| `--nldesign-font-weight-default` | `400` | | defaults | Base font size |
+| `--nldesign-font-weight-element` | `500` | | defaults | Control font weight |
+| `--nldesign-font-weight-heading` | `700` | | defaults | Heading font weight |
+
+## Spacing and shape (Ruimte en vorm)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-border-radius` | `8px` | | this set | Border radius element, Button corner, Input border width, Select corner, Text input corner |
+| `--nldesign-border-radius-large` | `12px` | | this set | Container radius |
+| `--nldesign-border-radius-pill` | `100px` | | this set | Badge shape, Border radius pill |
+| `--nldesign-border-radius-rounded` | `28px` | | this set | Border radius rounded |
+| `--nldesign-border-radius-small` | `4px` | | this set | Border radius small |
+| `--nldesign-component-badge-border-radius` | `var(
+ --nldesign-border-radius-pill
+ )` | | defaults | |
+| `--nldesign-component-badge-padding-block` | `0.125rem` | | defaults | |
+| `--nldesign-component-badge-padding-inline` | `0.5rem` | | defaults | |
+| `--nldesign-component-button-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-button-border-width` | `1px` | | defaults | |
+| `--nldesign-component-button-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-button-padding-inline` | `1rem` | | defaults | |
+| `--nldesign-component-form-fieldset-border-width` | `1px` | | defaults | |
+| `--nldesign-component-form-select-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-separator-border-width` | `1px` | | defaults | |
+| `--nldesign-component-table-border-width` | `1px` | | defaults | |
+| `--nldesign-component-table-cell-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-table-cell-padding-inline` | `0.75rem` | | defaults | |
+| `--nldesign-component-textbox-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-textbox-border-width` | `1px` | | defaults | |
+| `--nldesign-component-textbox-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-textbox-padding-inline` | `0.75rem` | | defaults | |
+| `--nldesign-header-border-bottom` | `1px solid rgba(138, 146, 158, 0.25)` | | this set | |
+| `--nldesign-logo-height` | `auto` | | defaults | |
+| `--nldesign-logo-width` | `121px` | | this set | |
+| `--nldesign-size-lint` | `0px` | | defaults | |
+| `--nldesign-size-lint-height` | `0px` | | defaults | |
+
+## Other tokens (Overige tokens)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-animation-easing` | `ease` | | defaults | |
+| `--nldesign-animation-quick` | `100ms` | | defaults | Header menu item height |
+| `--nldesign-animation-slow` | `300ms` | | defaults | Animation slow |
+| `--nldesign-header-icon-filter` | `invert(1) brightness(0) contrast(100)` | | defaults | |
+| `--nldesign-logo-bottom` | `1px` | | defaults | |
+| `--nldesign-logo-center` | `50%` | | defaults | |
+| `--nldesign-logo-filter` | `none` | | defaults | |
+| `--nldesign-logo-inset` | `12px` | | defaults | |
+| `--nldesign-logo-top` | `1px` | | defaults | |
+
+## Tokens nothing reads (Tokens die niets leest)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-brand-stripe-color-1` |  `#0B6E7A` |  `#79e0ec` | this set | |
+| `--nldesign-brand-stripe-color-2` |  `#E4E6EA` |  `#24272d` | this set | |
+| `--nldesign-brand-stripe-color-3` |  `#D9480F` |  `#e6612d` | this set | |
+| `--nldesign-brand-stripe-height` | `5px` | | this set | |
+| `--nldesign-brand-stripe-image` | `linear-gradient(to right, #0B6E7A 0 33.333%, #5FA3A8 33.333% 45.833%, #E4E6EA 45.833% 54.167%, #EFA06F 54.167% 66.667%, #D9480F 66.667%)` | | this set | |
+| `--nldesign-brand-stripe-ratio-1` | `11` | | this set | |
+| `--nldesign-brand-stripe-ratio-2` | `2` | | this set | |
+| `--nldesign-brand-stripe-ratio-3` | `11` | | this set | |
+| `--nldesign-component-content-card-shadow-color` |  `rgba(27, 28, 29, 0.04)` |  `#d2d3d40a` | this set | |
+| `--nldesign-component-content-surface-background-color` |  `#F5F6F8` |  `#171a20` | this set | |
+| `--nldesign-component-navigation-active-background-color` |  `#C2410C` |  `#e9713f` | this set | |
+| `--nldesign-component-navigation-active-color` |  `#9A3412` |  `#ed8765` | this set | |
+| `--nldesign-component-navigation-badge-background-color` |  `#C2410C` |  `#e9713f` | this set | |
+| `--nldesign-component-navigation-badge-color` |  `#ffffff` |  `#111111` | this set | |
+| `--nldesign-component-status-badge-error-background-color` |  `#FCEDEC` |  `#310d0a` | this set | |
+| `--nldesign-component-status-badge-error-color` |  `#A30000` |  `#ff5c5c` | this set | |
+| `--nldesign-component-status-badge-info-background-color` |  `#E3F1F3` |  `#182f33` | this set | |
+| `--nldesign-component-status-badge-info-color` |  `#084F58` |  `#a7eef7` | this set | |
+| `--nldesign-component-status-badge-success-background-color` |  `#E7F3EA` |  `#192e1e` | this set | |
+| `--nldesign-component-status-badge-success-color` |  `#1E6B2A` |  `#94e1a0` | this set | |
+| `--nldesign-component-status-badge-warning-background-color` |  `#FFF4DE` |  `#412d03` | this set | |
+| `--nldesign-component-status-badge-warning-color` |  `#7A4F00` |  `#ffd485` | this set | |
+| `--nldesign-login-watermark-image` | `url('../../img/logos/warmtepompacademie-emblem-grey.svg')` | | this set | |
+| `--nldesign-logo-url` | `url('../../img/logos/warmtepompacademie.svg')` | `url('../../../img/logos/warmtepompacademie-dark.svg')` | this set | |
+| `--nldesign-website-border-radius` | `3px` | | this set | |
+| `--nldesign-website-border-radius-large` | `6px` | | this set | |
+| `--warmtepompacademie-color-accent` |  `#C2410C` |  `#e9713f` | this set | |
+| `--warmtepompacademie-color-accent-light` |  `#FCEBDD` |  `#3f2109` | this set | |
+| `--warmtepompacademie-color-accent-mark` |  `#D9480F` |  `#e6612d` | this set | |
+| `--warmtepompacademie-color-accent-text` |  `#9A3412` |  `#ed8765` | this set | |
+| `--warmtepompacademie-color-ink` |  `#1B1C1D` |  `#d2d3d4` | this set | |
+| `--warmtepompacademie-color-line` |  `#E4E6EA` |  `#24272d` | this set | |
+| `--warmtepompacademie-color-main` |  `#0B6E7A` |  `#79e0ec` | this set | |
+| `--warmtepompacademie-color-main-deep` |  `#084F58` |  `#95e6f0` | this set | |
+| `--warmtepompacademie-color-main-light` |  `#E3F1F3` |  `#182f33` | this set | |
+| `--warmtepompacademie-color-muted` |  `#5E6168` |  `#93969c` | this set | |
+| `--warmtepompacademie-color-surface` |  `#F5F6F8` |  `#171a20` | this set | |
diff --git a/docs/reference/token-sets/wilgenboom.md b/docs/reference/token-sets/wilgenboom.md
new file mode 100644
index 000000000..f3d508938
--- /dev/null
+++ b/docs/reference/token-sets/wilgenboom.md
@@ -0,0 +1,300 @@
+
+
+# Basisschool De Wilgenboom
+
+Token set `wilgenboom`: 77 declared by this set, 129 from the defaults layer.
+
+Contrast: primary text on primary 6.32:1, primary on background 5.84:1 (pass).
+
+## Colours (Kleuren)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-color-background-dark` |  `#EDEFF2` |  `#1d2026` | this set | Background dark, Table header background |
+| `--nldesign-color-background-darker` |  `#D3D8DF` |  `#2d333c` | this set | Background darker |
+| `--nldesign-color-background-hover` |  `#F0F1F3` |  `#1d1f23` | this set | Main background color |
+| `--nldesign-color-border` |  `#E4E6EA` |  `#24272d` | this set | Border color, Select border, Table row rule, Text input border, `--nldesign-component-separator-border-color` |
+| `--nldesign-color-border-dark` |  `#8A929E` |  `#656c78` | this set | Border dark, Border max contrast |
+| `--nldesign-color-button-primary-background` |  `#2F6B4A` |  `#8cc8a7` | this set | |
+| `--nldesign-color-button-primary-border` |  `#2F6B4A` |  `#8cc8a7` | this set | |
+| `--nldesign-color-button-primary-hover` |  `#1F4A33` |  `#a7d6bd` | this set | |
+| `--nldesign-color-button-primary-text` |  `#ffffff` |  `#3e3e3e` | this set | |
+| `--nldesign-color-error` |  `#B30000` |  `#f54949` | this set | Border error, Element error, Error color, Text error, Text input invalid |
+| `--nldesign-color-error-hover` |  `#A30000` |  `#f65656` | this set | Error hover |
+| `--nldesign-color-error-rgb` | `179, 0, 0` | `245, 73, 73` | this set | Error text color |
+| `--nldesign-color-favorite` |  `#e17000` |  `#f48c25` | defaults | Background blur filter |
+| `--nldesign-color-focus` |  `rgba(47, 107, 74, 0.5)` |  `#8cc8a780` | this set | Button focus ring |
+| `--nldesign-color-focus-rgb` | `47, 107, 74` | `140, 200, 167` | this set | |
+| `--nldesign-color-header-background` |  `#ffffff` |  `#141414` | this set | |
+| `--nldesign-color-header-text` |  `#1B1C1D` |  `#e2e3e4` | this set | |
+| `--nldesign-color-info` |  `#2F6B4A` |  `#8cc8a7` | this set | Info color, Info hover color, Text input focus |
+| `--nldesign-color-info-rgb` | `47, 107, 74` | `140, 200, 167` | this set | |
+| `--nldesign-color-link` |  `#2F6B4A` |  `#8cc8a7` | this set | Link colour |
+| `--nldesign-color-link-hover` |  `#1F4A33` |  `#a7d6bd` | this set | Link hover colour |
+| `--nldesign-color-link-visited` |  `#42145f` |  `#c392e3` | defaults | `--nldesign-component-link-visited-color` |
+| `--nldesign-color-logo-background` | `transparent` | | defaults | |
+| `--nldesign-color-nav-background` |  `#ffffff` |  `#141414` | this set | |
+| `--nldesign-color-placeholder-dark` |  `#cccccc` |  `#3f3f3f` | defaults | Placeholder dark |
+| `--nldesign-color-placeholder-light` |  `#e5e5e5` |  `#2a2a2a` | defaults | Placeholder light |
+| `--nldesign-color-primary` |  `#2F6B4A` |  `#60b988` | this set | Badge background, Primary button background, Primary color, Primary element color, Primary element light text and 7 more |
+| `--nldesign-color-primary-hover` |  `#1F4A33` |  `#1f4a33` | this set | Primary button hover, Primary element hover, Primary hover color |
+| `--nldesign-color-primary-light` |  `#E8F1EB` |  `#1c2c21` | this set | Primary element light, Tertiary button hover, `--color-primary-element-text-dark` |
+| `--nldesign-color-primary-light-hover` |  `#DBE8E0` |  `#24362b` | this set | Primary element light hover, Primary light hover, Tertiary button pressed |
+| `--nldesign-color-primary-text` |  `#ffffff` |  `#111111` | this set | Badge number, Primary button label, Primary element text, Primary text color |
+| `--nldesign-color-success` |  `#1E6B2A` |  `#8ad896` | this set | Border success, Element success, Success color, Text success |
+| `--nldesign-color-success-rgb` | `30, 107, 42` | `138, 216, 150` | this set | Success hover color |
+| `--nldesign-color-text` |  `#1B1C1D` |  `#e2e3e4` | this set | Body text colour, Main text color, Table header label, `--nldesign-component-form-field-label-color`, `--nldesign-component-heading-1-color` and 8 more |
+| `--nldesign-color-text-light` |  `#ffffff` |  `#9e9e9e` | this set | Muted text default color |
+| `--nldesign-color-text-muted` |  `#5E6168` |  `#999ca3` | this set | Text lighter, Text max contrast |
+| `--nldesign-color-warning` |  `#7A4F00` |  `#f8ca77` | this set | Element warning, Text warning, Warning color |
+| `--nldesign-color-warning-rgb` | `122, 79, 0` | `248, 202, 119` | this set | Warning hover color |
+| `--nldesign-component-badge-background-color` | `var(
+ --nldesign-color-primary
+ )` |  `#8cc8a7` | defaults | |
+| `--nldesign-component-badge-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#3e3e3e` | defaults | |
+| `--nldesign-component-button-active-background-color` | `var(
+ --nldesign-color-primary-light-hover
+ )` |  `#24362b` | defaults | |
+| `--nldesign-component-button-active-color` | `var(
+ --nldesign-color-primary
+ )` |  `#94d0af` | defaults | |
+| `--nldesign-component-button-background-color` | `transparent` | | defaults | |
+| `--nldesign-component-button-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#8cc8a7` | defaults | |
+| `--nldesign-component-button-color` | `var(--nldesign-color-primary)` |  `#94d0af` | defaults | |
+| `--nldesign-component-button-disabled-background-color` |  `#e5e5e5` |  `#2a2a2a` | defaults | |
+| `--nldesign-component-button-disabled-border-color` |  `#b4b4b4` |  `#535353` | defaults | |
+| `--nldesign-component-button-disabled-color` |  `#696969` |  `#9e9e9e` | defaults | |
+| `--nldesign-component-button-focus-border-color` | `var(
+ --nldesign-color-focus
+ )` |  `#8cc8a780` | defaults | |
+| `--nldesign-component-button-hover-background-color` | `var(
+ --nldesign-color-primary-light
+ )` |  `#1c2c21` | defaults | |
+| `--nldesign-component-button-hover-border-color` | `var(
+ --nldesign-color-primary-hover
+ )` |  `#a7d6bd` | defaults | |
+| `--nldesign-component-button-hover-color` | `var(
+ --nldesign-color-primary
+ )` |  `#94d0af` | defaults | |
+| `--nldesign-component-button-primary-action-background-color` | `var(
+ --nldesign-color-primary
+ )` |  `#8cc8a7` | defaults | |
+| `--nldesign-component-button-primary-action-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#8cc8a7` | defaults | |
+| `--nldesign-component-button-primary-action-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#3e3e3e` | defaults | |
+| `--nldesign-component-button-primary-action-hover-background-color` | `var(
+ --nldesign-color-primary-hover
+ )` |  `#a7d6bd` | defaults | |
+| `--nldesign-component-button-primary-action-hover-color` | `var(
+ --nldesign-color-primary-text
+ )` |  `#3e3e3e` | defaults | |
+| `--nldesign-component-button-secondary-action-background-color` | `transparent` | | defaults | |
+| `--nldesign-component-button-secondary-action-border-color` | `var(
+ --nldesign-color-primary
+ )` |  `#8cc8a7` | defaults | |
+| `--nldesign-component-button-secondary-action-color` | `var(
+ --nldesign-color-primary
+ )` |  `#94d0af` | defaults | |
+| `--nldesign-component-button-secondary-action-hover-background-color` | `var(
+ --nldesign-color-primary-light
+ )` |  `#1c2c21` | defaults | |
+| `--nldesign-component-form-field-label-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-form-fieldset-border-color` | `var(
+ --nldesign-color-border
+ )` |  `#24272d` | defaults | |
+| `--nldesign-component-form-select-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-form-select-focus-border-color` | `var(--nldesign-color-info)` |  `#8cc8a7` | defaults | |
+| `--nldesign-component-heading-1-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-2-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-3-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-4-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-5-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-6-color` | `var(--nldesign-component-heading-color)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-heading-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-link-color` | `var(--nldesign-color-link)` |  `#94d0af` | defaults | |
+| `--nldesign-component-link-hover-color` | `var(--nldesign-color-link-hover)` |  `#b5e0c9` | defaults | |
+| `--nldesign-component-link-visited-color` | `var(--nldesign-color-link-visited)` |  `#cea0eb` | defaults | |
+| `--nldesign-component-ordered-list-color` | `var(
+ --nldesign-color-text
+ )` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-paragraph-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-separator-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-table-border-color` | `var(--nldesign-color-border)` |  `#24272d` | defaults | |
+| `--nldesign-component-table-header-background-color` | `var(
+ --nldesign-color-background-dark
+ )` |  `#1d2026` | defaults | |
+| `--nldesign-component-table-header-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-table-row-hover-background-color` | `var(
+ --nldesign-color-background-hover
+ )` |  `#1d1f23` | defaults | |
+| `--nldesign-component-textbox-background-color` |  `#ffffff` |  `#141414` | defaults | |
+| `--nldesign-component-textbox-border-color` | `var(--nldesign-color-border)` |  `#5d6474` | defaults | |
+| `--nldesign-component-textbox-color` | `var(--nldesign-color-text)` |  `#e2e3e4` | defaults | |
+| `--nldesign-component-textbox-disabled-background-color` |  `#e5e5e5` |  `#2a2a2a` | defaults | |
+| `--nldesign-component-textbox-disabled-color` |  `#696969` |  `#9e9e9e` | defaults | |
+| `--nldesign-component-textbox-focus-border-color` | `var(--nldesign-color-info)` |  `#8cc8a7` | defaults | |
+| `--nldesign-component-textbox-hover-border-color` | `var(
+ --nldesign-color-border-dark
+ )` |  `#656c78` | defaults | |
+| `--nldesign-component-textbox-invalid-border-color` | `var(--nldesign-color-error)` |  `#f54949` | defaults | |
+| `--nldesign-component-unordered-list-color` | `var(
+ --nldesign-color-text
+ )` |  `#e2e3e4` | defaults | |
+
+## Typography (Typografie)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-component-badge-font-size` | `0.875rem` | | defaults | |
+| `--nldesign-component-badge-font-weight` | `700` | | defaults | |
+| `--nldesign-component-button-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-button-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-button-font-weight` | `700` | | defaults | |
+| `--nldesign-component-form-field-label-font-weight` | `700` | | defaults | |
+| `--nldesign-component-heading-1-font-size` | `2.5rem` | | defaults | |
+| `--nldesign-component-heading-1-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-1-line-height` | `1.2` | | defaults | |
+| `--nldesign-component-heading-2-font-size` | `2rem` | | defaults | |
+| `--nldesign-component-heading-2-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-2-line-height` | `1.25` | | defaults | |
+| `--nldesign-component-heading-3-font-size` | `1.5rem` | | defaults | |
+| `--nldesign-component-heading-3-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-3-line-height` | `1.3` | | defaults | |
+| `--nldesign-component-heading-4-font-size` | `1.25rem` | | defaults | |
+| `--nldesign-component-heading-4-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-4-line-height` | `1.35` | | defaults | |
+| `--nldesign-component-heading-5-font-size` | `1.125rem` | | defaults | |
+| `--nldesign-component-heading-5-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-5-line-height` | `1.4` | | defaults | |
+| `--nldesign-component-heading-6-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-heading-6-font-weight` | `var(
+ --nldesign-component-heading-font-weight
+ )` | | defaults | |
+| `--nldesign-component-heading-6-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-heading-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-heading-font-weight` | `var(--nldesign-font-weight-heading)` | | defaults | |
+| `--nldesign-component-link-font-weight` | `var(
+ --nldesign-font-weight-default
+ )` | | defaults | |
+| `--nldesign-component-link-text-decoration` | `underline` | | defaults | |
+| `--nldesign-component-ordered-list-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-ordered-list-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-paragraph-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-paragraph-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-paragraph-font-weight` | `var(--nldesign-font-weight-default)` | | defaults | |
+| `--nldesign-component-paragraph-line-height` | `1.5` | | defaults | |
+| `--nldesign-component-table-header-font-weight` | `700` | | defaults | |
+| `--nldesign-component-textbox-font-family` | `var(--nldesign-font-family)` | | defaults | |
+| `--nldesign-component-textbox-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-unordered-list-font-size` | `1rem` | | defaults | |
+| `--nldesign-component-unordered-list-line-height` | `1.5` | | defaults | |
+| `--nldesign-font-family` | `'Lexend', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif` | | this set | Font family, `--nldesign-component-button-font-family`, `--nldesign-component-textbox-font-family` |
+| `--nldesign-font-weight-default` | `400` | | defaults | Base font size |
+| `--nldesign-font-weight-element` | `500` | | defaults | Control font weight |
+| `--nldesign-font-weight-heading` | `700` | | defaults | Heading font weight |
+
+## Spacing and shape (Ruimte en vorm)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-border-radius` | `8px` | | this set | Border radius element, Button corner, Input border width, Select corner, Text input corner |
+| `--nldesign-border-radius-large` | `12px` | | this set | Container radius |
+| `--nldesign-border-radius-pill` | `100px` | | this set | Badge shape, Border radius pill |
+| `--nldesign-border-radius-rounded` | `28px` | | this set | Border radius rounded |
+| `--nldesign-border-radius-small` | `4px` | | this set | Border radius small |
+| `--nldesign-component-badge-border-radius` | `var(
+ --nldesign-border-radius-pill
+ )` | | defaults | |
+| `--nldesign-component-badge-padding-block` | `0.125rem` | | defaults | |
+| `--nldesign-component-badge-padding-inline` | `0.5rem` | | defaults | |
+| `--nldesign-component-button-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-button-border-width` | `1px` | | defaults | |
+| `--nldesign-component-button-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-button-padding-inline` | `1rem` | | defaults | |
+| `--nldesign-component-form-fieldset-border-width` | `1px` | | defaults | |
+| `--nldesign-component-form-select-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-separator-border-width` | `1px` | | defaults | |
+| `--nldesign-component-table-border-width` | `1px` | | defaults | |
+| `--nldesign-component-table-cell-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-table-cell-padding-inline` | `0.75rem` | | defaults | |
+| `--nldesign-component-textbox-border-radius` | `var(--nldesign-border-radius)` | | defaults | |
+| `--nldesign-component-textbox-border-width` | `1px` | | defaults | |
+| `--nldesign-component-textbox-padding-block` | `0.5rem` | | defaults | |
+| `--nldesign-component-textbox-padding-inline` | `0.75rem` | | defaults | |
+| `--nldesign-header-border-bottom` | `1px solid rgba(138, 146, 158, 0.25)` | | this set | |
+| `--nldesign-logo-height` | `auto` | | defaults | |
+| `--nldesign-logo-width` | `153px` | | this set | |
+| `--nldesign-size-lint` | `0px` | | defaults | |
+| `--nldesign-size-lint-height` | `0px` | | defaults | |
+
+## Other tokens (Overige tokens)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-animation-easing` | `ease` | | defaults | |
+| `--nldesign-animation-quick` | `100ms` | | defaults | Header menu item height |
+| `--nldesign-animation-slow` | `300ms` | | defaults | Animation slow |
+| `--nldesign-header-icon-filter` | `invert(1) brightness(0) contrast(100)` | | defaults | |
+| `--nldesign-logo-bottom` | `1px` | | defaults | |
+| `--nldesign-logo-center` | `50%` | | defaults | |
+| `--nldesign-logo-filter` | `none` | | defaults | |
+| `--nldesign-logo-inset` | `12px` | | defaults | |
+| `--nldesign-logo-top` | `1px` | | defaults | |
+
+## Tokens nothing reads (Tokens die niets leest)
+
+| Token | Value | Dark mode | Source | Paints |
+|---|---|---|---|---|
+| `--nldesign-brand-stripe-color-1` |  `#2F6B4A` |  `#8cc8a7` | this set | |
+| `--nldesign-brand-stripe-color-2` |  `#F5B82E` |  `#cc9414` | this set | |
+| `--nldesign-brand-stripe-color-3` |  `#2F6B4A` |  `#8cc8a7` | this set | |
+| `--nldesign-brand-stripe-height` | `14px` | | this set | |
+| `--nldesign-brand-stripe-image` | `url("data:image/svg+xml,")` | | this set | |
+| `--nldesign-brand-stripe-ratio-1` | `3` | | this set | |
+| `--nldesign-brand-stripe-ratio-2` | `1` | | this set | |
+| `--nldesign-brand-stripe-ratio-3` | `3` | | this set | |
+| `--nldesign-component-content-card-shadow-color` |  `rgba(27, 28, 29, 0.04)` |  `#d2d3d40a` | this set | |
+| `--nldesign-component-content-surface-background-color` |  `#F5F6F8` |  `#171a20` | this set | |
+| `--nldesign-component-navigation-active-background-color` |  `#F5B82E` |  `#cc9414` | this set | |
+| `--nldesign-component-navigation-active-color` |  `#6B4A00` |  `#ffde94` | this set | |
+| `--nldesign-component-navigation-badge-background-color` |  `#F5B82E` |  `#cc9414` | this set | |
+| `--nldesign-component-navigation-badge-color` |  `#1A1A1A` |  `#111111` | this set | |
+| `--nldesign-component-status-badge-error-background-color` |  `#FCEDEC` |  `#310d0a` | this set | |
+| `--nldesign-component-status-badge-error-color` |  `#A30000` |  `#ff5c5c` | this set | |
+| `--nldesign-component-status-badge-info-background-color` |  `#E8F1EB` |  `#1c2c21` | this set | |
+| `--nldesign-component-status-badge-info-color` |  `#1F4A33` |  `#b5e0c9` | this set | |
+| `--nldesign-component-status-badge-success-background-color` |  `#E7F3EA` |  `#192e1e` | this set | |
+| `--nldesign-component-status-badge-success-color` |  `#1E6B2A` |  `#94e1a0` | this set | |
+| `--nldesign-component-status-badge-warning-background-color` |  `#FFF4DE` |  `#412d03` | this set | |
+| `--nldesign-component-status-badge-warning-color` |  `#7A4F00` |  `#ffd485` | this set | |
+| `--nldesign-login-watermark-image` | `url('../../img/logos/wilgenboom-emblem-grey.svg')` | | this set | |
+| `--nldesign-logo-url` | `url('../../img/logos/wilgenboom.svg')` | `url('../../../img/logos/wilgenboom-dark.svg')` | this set | |
+| `--nldesign-website-border-radius` | `10px` | | this set | |
+| `--nldesign-website-border-radius-large` | `14px` | | this set | |
+| `--wilgenboom-color-accent` |  `#F5B82E` |  `#cc9414` | this set | |
+| `--wilgenboom-color-accent-light` |  `#FDF3D7` |  `#453507` | this set | |
+| `--wilgenboom-color-accent-text` |  `#6B4A00` |  `#ffde94` | this set | |
+| `--wilgenboom-color-ink` |  `#1B1C1D` |  `#d2d3d4` | this set | |
+| `--wilgenboom-color-line` |  `#E4E6EA` |  `#24272d` | this set | |
+| `--wilgenboom-color-main` |  `#2F6B4A` |  `#8cc8a7` | this set | |
+| `--wilgenboom-color-main-deep` |  `#1F4A33` |  `#a7d6bd` | this set | |
+| `--wilgenboom-color-main-light` |  `#E8F1EB` |  `#1c2c21` | this set | |
+| `--wilgenboom-color-muted` |  `#5E6168` |  `#93969c` | this set | |
+| `--wilgenboom-color-surface` |  `#F5F6F8` |  `#171a20` | this set | |
diff --git a/img/ICONS.md b/img/ICONS.md
index 141adb5cd..c056614a6 100644
--- a/img/ICONS.md
+++ b/img/ICONS.md
@@ -273,7 +273,7 @@ PHP/template and other non-Vue consumers.
These URLs only resolve while the nldesign app is enabled. Consumers must ship a fallback
icon or declare a dependency on `nldesign`.
-## Logos (41 total)
+## Logos (57 total)
Available in: `img/logos/`. Static, checked-in huisstijl assets tied to token sets
(`token-sets.json` `theming.logo` entries) — organisation marks displayed as that
@@ -286,6 +286,10 @@ organisation's own identity on that organisation's own instance. **Not build out
- drechterland
- epe
- epe-dark
+- esdoornveen
+- esdoornveen-dark
+- esdoornveen-emblem
+- esdoornveen-emblem-grey
- example-basisschool
- example-college
- example-gemeente
@@ -312,9 +316,21 @@ organisation's own identity on that organisation's own instance. **Not build out
- tilburg
- tubbergen
- utrecht
+- vaartveld
+- vaartveld-dark
+- vaartveld-emblem
+- vaartveld-emblem-grey
- vga-verzekeringen
- vng
- vng-dark
+- warmtepompacademie
+- warmtepompacademie-dark
+- warmtepompacademie-emblem
+- warmtepompacademie-emblem-grey
+- wilgenboom
+- wilgenboom-dark
+- wilgenboom-emblem
+- wilgenboom-emblem-grey
- xxllnc
- xxllnc-dark
- zuiddrecht
diff --git a/img/logos/esdoornveen-dark.svg b/img/logos/esdoornveen-dark.svg
new file mode 100644
index 000000000..78f631114
--- /dev/null
+++ b/img/logos/esdoornveen-dark.svg
@@ -0,0 +1,10 @@
+
diff --git a/img/logos/esdoornveen-emblem-grey.svg b/img/logos/esdoornveen-emblem-grey.svg
new file mode 100644
index 000000000..cdefeb8ec
--- /dev/null
+++ b/img/logos/esdoornveen-emblem-grey.svg
@@ -0,0 +1,8 @@
+
diff --git a/img/logos/esdoornveen-emblem.svg b/img/logos/esdoornveen-emblem.svg
new file mode 100644
index 000000000..5ebee1bf3
--- /dev/null
+++ b/img/logos/esdoornveen-emblem.svg
@@ -0,0 +1,8 @@
+
diff --git a/img/logos/esdoornveen.svg b/img/logos/esdoornveen.svg
new file mode 100644
index 000000000..a602d4098
--- /dev/null
+++ b/img/logos/esdoornveen.svg
@@ -0,0 +1,10 @@
+
diff --git a/img/logos/vaartveld-dark.svg b/img/logos/vaartveld-dark.svg
new file mode 100644
index 000000000..27a0c4b4d
--- /dev/null
+++ b/img/logos/vaartveld-dark.svg
@@ -0,0 +1,7 @@
+
diff --git a/img/logos/vaartveld-emblem-grey.svg b/img/logos/vaartveld-emblem-grey.svg
new file mode 100644
index 000000000..7e01df33c
--- /dev/null
+++ b/img/logos/vaartveld-emblem-grey.svg
@@ -0,0 +1,5 @@
+
diff --git a/img/logos/vaartveld-emblem.svg b/img/logos/vaartveld-emblem.svg
new file mode 100644
index 000000000..6afe1b4b1
--- /dev/null
+++ b/img/logos/vaartveld-emblem.svg
@@ -0,0 +1,5 @@
+
diff --git a/img/logos/vaartveld.svg b/img/logos/vaartveld.svg
new file mode 100644
index 000000000..ff2a37b94
--- /dev/null
+++ b/img/logos/vaartveld.svg
@@ -0,0 +1,7 @@
+
diff --git a/img/logos/warmtepompacademie-dark.svg b/img/logos/warmtepompacademie-dark.svg
new file mode 100644
index 000000000..e22fdba81
--- /dev/null
+++ b/img/logos/warmtepompacademie-dark.svg
@@ -0,0 +1,7 @@
+
diff --git a/img/logos/warmtepompacademie-emblem-grey.svg b/img/logos/warmtepompacademie-emblem-grey.svg
new file mode 100644
index 000000000..becf2d97d
--- /dev/null
+++ b/img/logos/warmtepompacademie-emblem-grey.svg
@@ -0,0 +1,5 @@
+
diff --git a/img/logos/warmtepompacademie-emblem.svg b/img/logos/warmtepompacademie-emblem.svg
new file mode 100644
index 000000000..95bfcb70e
--- /dev/null
+++ b/img/logos/warmtepompacademie-emblem.svg
@@ -0,0 +1,5 @@
+
diff --git a/img/logos/warmtepompacademie.svg b/img/logos/warmtepompacademie.svg
new file mode 100644
index 000000000..609f404fb
--- /dev/null
+++ b/img/logos/warmtepompacademie.svg
@@ -0,0 +1,7 @@
+
diff --git a/img/logos/wilgenboom-dark.svg b/img/logos/wilgenboom-dark.svg
new file mode 100644
index 000000000..4f4028ab8
--- /dev/null
+++ b/img/logos/wilgenboom-dark.svg
@@ -0,0 +1,11 @@
+
diff --git a/img/logos/wilgenboom-emblem-grey.svg b/img/logos/wilgenboom-emblem-grey.svg
new file mode 100644
index 000000000..fb55e5ce8
--- /dev/null
+++ b/img/logos/wilgenboom-emblem-grey.svg
@@ -0,0 +1,9 @@
+
diff --git a/img/logos/wilgenboom-emblem.svg b/img/logos/wilgenboom-emblem.svg
new file mode 100644
index 000000000..686925fa9
--- /dev/null
+++ b/img/logos/wilgenboom-emblem.svg
@@ -0,0 +1,9 @@
+
diff --git a/img/logos/wilgenboom.svg b/img/logos/wilgenboom.svg
new file mode 100644
index 000000000..c65574ae7
--- /dev/null
+++ b/img/logos/wilgenboom.svg
@@ -0,0 +1,11 @@
+
diff --git a/openspec/changes/school-token-sets/proposal.md b/openspec/changes/school-token-sets/proposal.md
new file mode 100644
index 000000000..dde6fe7fd
--- /dev/null
+++ b/openspec/changes/school-token-sets/proposal.md
@@ -0,0 +1,59 @@
+---
+kind: code
+---
+
+## Why
+
+Zuiddrecht, the demo municipality, has four schools in the same demo world: Basisschool De
+Wilgenboom, Vaartveld College, Esdoornveen (an mbo college) and the Warmtepompacademie. Each has
+a finished design (a house style for the website and a workplace layer on Cunningham). A demo of
+learniq or portaliq for a school should wear that school's design, not a municipality's and not
+the generic `example-*` sets, the way a municipal demo wears `zuiddrecht`.
+
+Most of each design is a token set built exactly as `zuiddrecht` is. Three things in the designs
+had no place to land yet: a motif that is not three flat bands, website corners that differ from
+the workplace's, and a heading face that differs from the text face on the website.
+
+## What Changes
+
+- **Four token sets**, `wilgenboom`, `vaartveld`, `esdoornveen` and `warmtepompacademie`, each
+ with `css/tokens/.css`, a generated dark variant, `css/token-overrides/.css`, four
+ logos (colour, white, emblem, grey emblem), a `token-sets.json` entry with a `layout` block and
+ a generated reference page. The colours, faces and radii are the designs'.
+- **Seven typefaces bundled** (SIL OFL 1.1, Fontsource 5.3.0, latin, woff2): Lexend 400 to 700,
+ Red Hat Display 600 to 800, Red Hat Text 400 to 700, Barlow 400 to 700, Barlow Semi Condensed
+ 600 and 700, IBM Plex Sans 500 (joining 400, 600 and 700) and IBM Plex Mono 400 and 500.
+- **The brand stripe may draw an image.** `--nldesign-brand-stripe-image`, when a set names it,
+ replaces the three bands in the same box. The schools draw their motifs with it: the hanging
+ twigs, the canal and its bank, the slanted cut and the temperature line.
+- **Website corners.** `--nldesign-website-border-radius` (buttons and fields) and
+ `--nldesign-website-border-radius-large` (cards, dialogs, messages), read only by
+ `css/public-bridge.css`, which a portal links and an instance page never does. The workplace
+ keeps 8px and 12px.
+- **Website headings.** The public bridge hands `--nldesign-component-heading-font-family`, the
+ token Nextcloud's headings already read, to the website's heading roles.
+
+**Out of scope:** the motifs in the website header and footer. The designs place them in
+portaliq's header and footer, and portaliq draws no motif today, not even Zuiddrecht's three
+bands; that is portaliq's work. Den Haag's mijn-omgeving components keep reading
+`--nldesign-border-radius` (generated from `scripts/mapping/denhaag-component-tokens.json`), so
+their corners follow the workplace scale.
+
+## Capabilities
+
+### New Capabilities
+- `school-token-sets`: what each school set declares, the contrast every text pair reaches, the
+ motif in the brand stripe and the website corners and heading face.
+
+## Impact
+
+- New files: four token files, four dark variants, four overrides files, sixteen logos, four
+ reference pages, nineteen font files per font directory.
+- Changed: `css/brand-stripe.css` (one `var()` around the gradient), `css/public-bridge.css`
+ (seven radius roles, four heading roles), `scripts/build-fonts.js` (the families table; IBM
+ Plex Mono moves from the notice-only table into it), `REUSE.toml`.
+- No set changes: every new token is undeclared in every existing set, the bridge roles resolve
+ to the guaranteed-invalid value when a set names no website radius (a consumer's own fallback
+ then applies), and the heading roles fall back to the text face. `example-basisschool`,
+ `example-voortgezet`, `example-college` and `example-opleider` are untouched.
+- No migration. Additive, so a minor version.
diff --git a/openspec/changes/school-token-sets/specs/school-token-sets/spec.md b/openspec/changes/school-token-sets/specs/school-token-sets/spec.md
new file mode 100644
index 000000000..6d5a0c7f7
--- /dev/null
+++ b/openspec/changes/school-token-sets/specs/school-token-sets/spec.md
@@ -0,0 +1,117 @@
+# Spec: School token sets
+
+Four demo schools in Zuiddrecht, each with a token set built the way `zuiddrecht` is.
+
+## ADDED Requirements
+
+### Requirement: Each school set declares its design's palette
+`css/tokens/.css` MUST be one flat `:root` block on the `--nldesign-*` vocabulary, for
+`wilgenboom`, `vaartveld`, `esdoornveen` and `warmtepompacademie`. The interactive colour and its
+hover MUST be the design's main and main-deep colours (#2F6B4A and #1F4A33, #1F4FD8 and #14338F,
+#5B2E91 and #43206E, #0B6E7A and #084F58). The accent MUST colour the selected navigation entry
+and the navigation count badge, with the design's accent text colour as the entry's label, and
+MUST NOT be the primary colour. `token-sets.json` MUST list each set on the `nldesign` design
+system with its primary colour, background colour #F5F6F8, a logo and a dark logo.
+
+#### Scenario: The vocabulary audit passes
+@e2e exclude Static file check: PHPUnit tests/Unit/TokenSetVocabularyTest.php and `npm run audit:token-sets:check` audit every shipped set
+- GIVEN the shipped token sets
+- WHEN the vocabulary audit runs
+- THEN each school set MUST be complete: no missing required token, no name nothing reads, and a primary colour equal to the manifest's
+
+#### Scenario: The palette is the design's
+@e2e exclude Static file check: tests/vitest/schoolTokenSets.spec.js reads each token file and the manifest
+- GIVEN a school set's token file
+- WHEN its colours are read
+- THEN the primary, its hover, the primary-light tint, the link, the primary button and the accent tokens MUST equal the design's values
+
+#### Scenario: The example sets stay
+@e2e exclude Static file check: tests/vitest/schoolTokenSets.spec.js reads the manifest
+- GIVEN installed instances that reference `example-basisschool`, `example-voortgezet`, `example-college` or `example-opleider`
+- WHEN the school sets are added
+- THEN those four sets MUST still be listed under their own ids with their own token files
+
+### Requirement: Every text pair reaches AA
+Every text and background pair a school set names MUST reach 4.5:1 in the light scheme and in
+both dark scopes, and a control border MUST reach 3:1 against a card. Where the accent is too
+light to carry white (wilgenboom, vaartveld), the solid selected entry MUST carry ink instead.
+Where the generated dark variant falls short, `css/token-overrides/.css` MUST set the value
+by hand for the two dark scopes.
+
+#### Scenario: Light and dark pairs
+@e2e exclude Computed from the token files: tests/vitest/schoolTokenSets.spec.js resolves the light file, the generated dark file and the overrides, and computes each ratio
+- GIVEN a school set's light file, generated dark file and overrides
+- WHEN each named pair is computed against the main background and the workspace
+- THEN text, muted text, link, status text, the primary button label, the header text, the selected entry's label on its wash and on its solid fill, the badge number and each status pill MUST reach 4.5:1
+
+#### Scenario: The dark workspace sits below the cards
+@e2e exclude Static file check: tests/vitest/schoolTokenSets.spec.js reads the overrides file
+- GIVEN a school set's overrides file
+- WHEN its dark scopes are read
+- THEN the page background and the content surface MUST be #121315, darker than Nextcloud's dark cards
+
+### Requirement: Each school set wears the light workplace
+Each school set's manifest entry MUST carry `workplace_layout: light`. `esdoornveen`, whose
+designed Nextcloud login shows its 6px motif and whose motif fits inside the top bar as
+zuiddrecht's 5px stripe does, MUST also carry `brand_stripe: true`. The other three MUST NOT:
+the designed workplace bar of all four carries no motif, wilgenboom's 14px twigs would cover the
+bottom of the logo and the search field inside the 50px bar, and the designed Nextcloud login of
+vaartveld and warmtepompacademie shows none. Their motifs stay declared, so an administrator who
+turns the stripe on gets them. The workplace MUST keep
+Nextcloud's radius scale: 8px controls, 12px containers.
+
+#### Scenario: The layout follows the set
+@e2e exclude Pure service logic: PHPUnit tests/Unit/Service/LayoutOptionsServiceTest.php resolves each set with nothing stored
+- GIVEN an instance with no stored layout choice
+- WHEN a school set is active
+- THEN the workplace layout MUST be `light`, and the brand stripe MUST be on for `esdoornveen` only
+
+### Requirement: Each school set ships its logos and a login watermark
+`img/logos/` MUST hold `.svg`, `-dark.svg`, `-emblem.svg` and
+`-emblem-grey.svg` for each school set, each a self-contained SVG. The token file MUST name
+the grey emblem as the login watermark, and the overrides file MUST give the wordmark 200 by 44
+pixels on the login card.
+
+#### Scenario: The logos are there
+@e2e exclude Static file check: tests/vitest/schoolTokenSets.spec.js and PHPUnit tests/Unit/Service/SetLogoReachTest.php read the logo directory
+- GIVEN the logo directory
+- WHEN a school set's four files are read
+- THEN each MUST start with `