customisation-l1 · html
L1 brand
Copy this page into your project. Recolour it with tokens. It is yours from that moment.
), once for light and once for dark. Nothing
* else on the page changes: the Northline markup below is identical to
* the homepage, and every button, badge and alert recolours itself.
*/
:root {
--bw-font-family-sans: "Source Sans 3", system-ui, sans-serif;
--bw-font-family-display: "Source Serif 4", Georgia, serif;
}
/* L1 brand pack: load-bearing tokens only (light + dark). */
:root,
[data-theme="light"] {
--bw-color-accent: oklch(0.55 0.19 25);
--bw-color-fg-on-accent: oklch(0.99 0 0);
--bw-color-surface: oklch(0.99 0.005 90);
--bw-color-fg: oklch(0.22 0.02 40);
--bw-color-border: oklch(0.88 0.01 40);
--bw-color-danger: oklch(0.55 0.2 25);
--bw-color-success: oklch(0.55 0.14 150);
--bw-color-warning: oklch(0.7 0.15 75);
}
[data-theme="dark"] {
--bw-color-accent: oklch(0.7 0.16 25);
--bw-color-fg-on-accent: oklch(0.18 0.02 40);
--bw-color-surface: oklch(0.2 0.02 40);
--bw-color-fg: oklch(0.95 0.01 90);
--bw-color-border: oklch(0.35 0.02 40);
--bw-color-danger: oklch(0.7 0.16 25);
--bw-color-success: oklch(0.72 0.12 150);
--bw-color-warning: oklch(0.78 0.12 75);
}
body {
--bw-color-accent-fg: var(--bw-color-fg-on-accent);
margin: 0;
font-family: var(--bw-font-family-sans);
background: var(--bw-color-surface);
color: var(--bw-color-fg);
}
.nl-header {
display: flex;
align-items: center;
gap: var(--bw-space-5);
padding: var(--bw-space-4) var(--bw-space-6);
border-bottom: 1px solid var(--bw-color-border);
background: var(--bw-color-surface);
}
.nl-header__brand {
display: inline-flex;
align-items: center;
gap: var(--bw-space-2);
margin-right: auto;
font-weight: 700;
letter-spacing: -0.03em;
color: var(--bw-color-fg);
text-decoration: none;
}
.nl-header__mark {
width: 1.125rem;
height: 1.125rem;
border-radius: 5px;
background: var(--bw-color-accent);
}
.nl-header__nav {
display: flex;
align-items: center;
gap: var(--bw-space-5);
}
.nl-header__nav a {
color: var(--bw-color-fg-muted);
text-decoration: none;
font-size: var(--bw-font-size-sm);
font-weight: 500;
}
.nl-header__nav a:hover {
color: var(--bw-color-fg);
}
.nl-footer {
display: flex;
flex-wrap: wrap;
gap: var(--bw-space-4);
justify-content: space-between;
padding: var(--bw-space-6);
border-top: 1px solid var(--bw-color-border);
color: var(--bw-color-fg-muted);
font-size: var(--bw-font-size-sm);
}
.nl-footer p {
margin: 0;
}
.nl-footer a {
color: inherit;
}
.nl-eyebrow {
margin: 0;
font-size: var(--bw-font-size-sm);
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--bw-color-fg-muted);
}
.nl-heading {
margin: 0;
font-family: var(--bw-font-family-display);
font-weight: 650;
font-size: clamp(2rem, 4vw, 3rem);
line-height: 1.1;
letter-spacing: -0.02em;
text-wrap: balance;
}
.nl-lede {
margin: 0;
max-inline-size: 44ch;
font-size: var(--bw-font-size-lg);
line-height: 1.5;
color: var(--bw-color-fg-muted);
}
.nl-actions {
display: flex;
flex-wrap: wrap;
gap: var(--bw-space-3);
}
@media (max-width: 48rem) {
.nl-header__nav {
display: none;
}
}
.nl-recolour {
display: grid;
gap: var(--bw-space-6);
max-inline-size: 44rem;
margin-inline: auto;
padding: var(--bw-space-10) var(--bw-space-6);
}
.nl-recolour__intro {
display: grid;
gap: var(--bw-space-3);
}
.nl-fragment {
display: grid;
gap: var(--bw-space-4);
padding: var(--bw-space-6);
border: 1px solid var(--bw-color-border);
border-radius: var(--bw-radius-lg);
background: var(--bw-color-surface);
}
.nl-fragment__top {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: var(--bw-space-3);
}
.nl-fragment__title {
margin: 0;
font-family: var(--bw-font-family-display);
font-weight: 650;
font-size: var(--bw-font-size-xl);
letter-spacing: -0.01em;
}
.nl-fragment__body {
margin: 0;
color: var(--bw-color-fg-muted);
line-height: 1.5;
}
.nl-fragment .bw-alert {
margin-block-end: 0;
}
.nl-recolour__note {
margin: 0;
font-size: var(--bw-font-size-sm);
color: var(--bw-color-fg-muted);
}
Skip to content
Northline
Book a walkthrough
Themes · L1 brand pack
Recolour with an L1 brand pack
Swap one short block of colour tokens and the whole product follows. This page is Northline in a warm terracotta pack; the markup is unchanged.
Mersey hub: morning board
2 late loadsFourteen routes are live. Two loads are running behind and the customer has not been told yet.
Route 14 is 22 minutes behind
See the default teal pack on the homepage and the landing page.
Paste into a static page. Link @bwui/css (and @bwui/js for behaviours).
<!DOCTYPE html>
<html lang="en-GB" data-bw-brand="northline">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Recolour with an L1 brand pack | Northline</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Source+Sans+3:wght@400;500;600;700&family=Source+Serif+4:opsz,wght@8..60,500;8..60,650;8..60,700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="/static/product_templates/assets/brickwork.css" />
<script defer src="/static/product_templates/assets/behaviours.js"></script>
<style>
/*
* Recolour with an L1 brand pack.
*
* Teaching point: a brand is a short block of load-bearing --bw-color-*
* tokens, declared after the kit CSS on the element that carries
* data-theme (here <body>), once for light and once for dark. Nothing
* else on the page changes: the Northline markup below is identical to
* the homepage, and every button, badge and alert recolours itself.
*/
:root {
--bw-font-family-sans: "Source Sans 3", system-ui, sans-serif;
--bw-font-family-display: "Source Serif 4", Georgia, serif;
}
/* L1 brand pack: load-bearing tokens only (light + dark). */
:root,
[data-theme="light"] {
--bw-color-accent: oklch(0.55 0.19 25);
--bw-color-fg-on-accent: oklch(0.99 0 0);
--bw-color-surface: oklch(0.99 0.005 90);
--bw-color-fg: oklch(0.22 0.02 40);
--bw-color-border: oklch(0.88 0.01 40);
--bw-color-danger: oklch(0.55 0.2 25);
--bw-color-success: oklch(0.55 0.14 150);
--bw-color-warning: oklch(0.7 0.15 75);
}
[data-theme="dark"] {
--bw-color-accent: oklch(0.7 0.16 25);
--bw-color-fg-on-accent: oklch(0.18 0.02 40);
--bw-color-surface: oklch(0.2 0.02 40);
--bw-color-fg: oklch(0.95 0.01 90);
--bw-color-border: oklch(0.35 0.02 40);
--bw-color-danger: oklch(0.7 0.16 25);
--bw-color-success: oklch(0.72 0.12 150);
--bw-color-warning: oklch(0.78 0.12 75);
}
body {
--bw-color-accent-fg: var(--bw-color-fg-on-accent);
margin: 0;
font-family: var(--bw-font-family-sans);
background: var(--bw-color-surface);
color: var(--bw-color-fg);
}
.nl-header {
display: flex;
align-items: center;
gap: var(--bw-space-5);
padding: var(--bw-space-4) var(--bw-space-6);
border-bottom: 1px solid var(--bw-color-border);
background: var(--bw-color-surface);
}
.nl-header__brand {
display: inline-flex;
align-items: center;
gap: var(--bw-space-2);
margin-right: auto;
font-weight: 700;
letter-spacing: -0.03em;
color: var(--bw-color-fg);
text-decoration: none;
}
.nl-header__mark {
width: 1.125rem;
height: 1.125rem;
border-radius: 5px;
background: var(--bw-color-accent);
}
.nl-header__nav {
display: flex;
align-items: center;
gap: var(--bw-space-5);
}
.nl-header__nav a {
color: var(--bw-color-fg-muted);
text-decoration: none;
font-size: var(--bw-font-size-sm);
font-weight: 500;
}
.nl-header__nav a:hover {
color: var(--bw-color-fg);
}
.nl-footer {
display: flex;
flex-wrap: wrap;
gap: var(--bw-space-4);
justify-content: space-between;
padding: var(--bw-space-6);
border-top: 1px solid var(--bw-color-border);
color: var(--bw-color-fg-muted);
font-size: var(--bw-font-size-sm);
}
.nl-footer p {
margin: 0;
}
.nl-footer a {
color: inherit;
}
.nl-eyebrow {
margin: 0;
font-size: var(--bw-font-size-sm);
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--bw-color-fg-muted);
}
.nl-heading {
margin: 0;
font-family: var(--bw-font-family-display);
font-weight: 650;
font-size: clamp(2rem, 4vw, 3rem);
line-height: 1.1;
letter-spacing: -0.02em;
text-wrap: balance;
}
.nl-lede {
margin: 0;
max-inline-size: 44ch;
font-size: var(--bw-font-size-lg);
line-height: 1.5;
color: var(--bw-color-fg-muted);
}
.nl-actions {
display: flex;
flex-wrap: wrap;
gap: var(--bw-space-3);
}
@media (max-width: 48rem) {
.nl-header__nav {
display: none;
}
}
.nl-recolour {
display: grid;
gap: var(--bw-space-6);
max-inline-size: 44rem;
margin-inline: auto;
padding: var(--bw-space-10) var(--bw-space-6);
}
.nl-recolour__intro {
display: grid;
gap: var(--bw-space-3);
}
.nl-fragment {
display: grid;
gap: var(--bw-space-4);
padding: var(--bw-space-6);
border: 1px solid var(--bw-color-border);
border-radius: var(--bw-radius-lg);
background: var(--bw-color-surface);
}
.nl-fragment__top {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: var(--bw-space-3);
}
.nl-fragment__title {
margin: 0;
font-family: var(--bw-font-family-display);
font-weight: 650;
font-size: var(--bw-font-size-xl);
letter-spacing: -0.01em;
}
.nl-fragment__body {
margin: 0;
color: var(--bw-color-fg-muted);
line-height: 1.5;
}
.nl-fragment .bw-alert {
margin-block-end: 0;
}
.nl-recolour__note {
margin: 0;
font-size: var(--bw-font-size-sm);
color: var(--bw-color-fg-muted);
}
</style>
</head>
<body data-theme="light" data-bw-brand="northline">
<a class="bw-skip-link" href="#main">Skip to content</a>
<header class="nl-header">
<a class="nl-header__brand" href="/templates/homepage/full/">
<span class="nl-header__mark" aria-hidden="true"></span>
Northline
</a>
<nav class="nl-header__nav" aria-label="Primary">
<a href="/templates/homepage/full/">Product</a>
<a href="/templates/landing/full/">Customers</a>
<a href="/templates/pricing/full/">Pricing</a>
</nav>
<a class="bw-btn bw-btn--solid" href="/templates/contact/full/">Book a walkthrough</a>
</header>
<main id="main" class="nl-recolour">
<div class="nl-recolour__intro">
<p class="nl-eyebrow">Themes · L1 brand pack</p>
<h1 class="nl-heading">Recolour with an L1 brand pack</h1>
<p class="nl-lede">
Swap one short block of colour tokens and the whole product follows. This page is Northline in a warm
terracotta pack; the markup is unchanged.
</p>
</div>
<section class="nl-fragment" aria-labelledby="nl-fragment-title">
<div class="nl-fragment__top">
<h2 class="nl-fragment__title" id="nl-fragment-title">Mersey hub: morning board</h2>
<span class="bw-badge bw-badge--danger">2 late loads</span>
</div>
<p class="nl-fragment__body">
Fourteen routes are live. Two loads are running behind and the customer has not been told yet.
</p>
<div class="bw-alert bw-alert--danger" role="status">
<svg class="bw-alert__icon" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" aria-hidden="true">
<circle cx="10" cy="10" r="8" />
<path d="M10 5.75v5M10 14.1h.01" />
</svg>
<div class="bw-alert__body">
<p class="bw-alert__title">Route 14 is 22 minutes behind</p>
<p class="bw-alert__message">Driver handoff at Widnes missed its window. Send the revised ETA before the customer rings.</p>
</div>
</div>
<div class="nl-actions">
<button class="bw-btn bw-btn--solid" type="button">Send revised ETA</button>
<button class="bw-btn bw-btn--ghost" type="button">Reassign driver</button>
<button class="bw-btn bw-btn--ghost" type="button" onclick="document.body.dataset.theme=document.body.dataset.theme==='dark'?'light':'dark';document.documentElement.dataset.theme=document.body.dataset.theme">
Toggle theme
</button>
</div>
</section>
<p class="nl-recolour__note">
See the default teal pack on the <a href="/templates/homepage/full/">homepage</a> and the
<a href="/templates/landing/full/">landing page</a>.
</p>
</main>
<footer class="nl-footer">
<p>© Northline. Fleet operations software for depots and drivers.</p>
<p><a href="/templates/homepage/full/">Homepage</a> · <a href="/templates/landing/full/">Landing</a> · <a href="/templates/contact/full/">Contact</a></p>
</footer>
</body>
</html>