Component Library

All UI components used across the site, grouped by type. Each component shows its name, CSS class(es), a short description, a live preview, and which pages use it.


Colour Palette — Semantic Colours

All values are CSS custom properties defined in :root (light) and [data-theme="dark"] in main.css. Toggle dark mode in the sidebar to see both sets live.

--background-color Light: #ffffff
Dark: #0d1417
--text-color Light: #191b1c
Dark: #f4f6f8
--text-color-grey Both: #808492
--link-color Light: #0059cc
Dark: #529dfe
--highlights Light: #ffe526
Dark: #0062ff
--hr-line Light: #000000
Dark: #dde7ec
--input-border Light: #687b8d
Dark: #E9EDF1

Colour Palette — UI & Interactive

--button-bg Light: #2563eb
Dark: #3b82f6
--button-hover Light: #1d4ed8
Dark: #60a5fa
--button-active Light: #1e40af
Dark: #93c5fd
--font-chip-bg Light: #d8e6ff
Dark: #002058
--font-chip-bghov Light: #d8e6ff
Dark: #003078
--focus-ring Light: rgba(37,99,235,.5)
Dark: rgba(59,130,246,.5)
--pause-button-hover Light: #fff494
Dark: #b49901
--stop-button-hover Light: #fc9494
Dark: #ff3300

Colour Palette — Navigation

--background-color-nav Light: #dfe9f9ac
Dark: #182830e5
--background-color-nav-unsup Light: #dfe9f9
Dark: #182830
--background-color-nav-hover Light: #bad3fbcc
Dark: #070e11e5
--nav-link-hover Light: #196AE3
Dark: #4AB7FF
--toggle-bg Light: #e5e7eb
Dark: #4b5563
--switch-bg Light: #0062ff
Dark: #cadeff

Colour Palette — Miscellaneous

--wiseness-light Light: #e9effa
Dark: #0e1a20
--wiseness-dark Light: #e5efff
Dark: #0c161c
--wiseness-font Light: #062e6f
Dark: #3b82f6
--scrollbar-background Light: #eaeff8
Dark: #13242c
--scrollbar-thumb Light: #a7c1f1
Dark: #264b5d
--slides-primary-color Light: #f4f6f8d1
Dark: #040a0dd6

Colour Palette — Type Scale

Defined in :root in typography.css. Base is 16px; all sizes use rem.

Aa
--font-size-base 1.063rem / 17px
Aa
--font-size-md 1.25rem / 20px
Aa
--font-size-lg 1.5rem / 24px
Aa
--font-size-xl 2rem / 32px
Aa
--font-size-2xl 2.7rem / 43.2px
Aa
--font-size-3xl 4.25rem / 68px
Aa
--font-size-4xl 6rem / 96px

Typography — Display Classes

Display 1 .display-1

Largest headline, 96px / weight 600. Used as primary hero heading on every page.

Used on: index.html, conversational_v2.html, Ecosystem_V2.html, project_template.html, about.html, contacts.html

Designer and Maker.

Display 2 .display-2

43.2px / weight 500. Secondary large headline, often used for section titles or pull quotes.

Used on: index.html, about.html, project pages

A generalist with a soft spot for complex systems.

Display 3 .display-3

32px / weight 500. Tertiary display, commonly used for subtitles under hero headings.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html, index.html

When a conversational interface helps, and when it doesn't.

Display 4 .display-4

56px / weight 600. Used for prominent featured text between display-1 and display-2 in size.

Used on: index.html, about.html

Featured statement.

Display 5 .display-5

24px / weight 600. Smallest display class, used for supporting text or small section intros.

Used on: index.html, various content pages

A smaller but still prominent statement.

Quotes .Quotes

68px / weight 600. Large pull-quote style. Often combined with .highlights for emphasis.

Used on: about.html, contacts.html, project pages

"The answer is inside you. But it's wrong"

Typography — Headings

h1 – h4 (native elements)

Base heading styles applied globally. h1: 68px/600. h2: 43.2px/600. h3: 32px/600. h4: 24px/700.

Used on: All pages

h1 — Section Title

h2 — Section Heading

h3 — Subsection Heading

h4 — Small Heading

Typography — Body Text

Body paragraph body / p

Base body text: Plus Jakarta Sans, 17px, line-height 2em. Applied globally via the body rule.

Used on: All pages

The bad news is that buying a car is a messy business, and people take a substantial amount of time dealing with their emotions — a rollercoaster spanning excitement, doubt, confusion and joy.

Article paragraph .article p

20px / Atkinson Hyperlegible, line-height 1.5. Applied to paragraphs inside an .article wrapper. Optimised for readability in long-form content.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html, what_ai_exposes.html, AI_tracking_for_elderly_people.html

The goal wasn't to have complete online sales, but rather to drive more people down the funnel, increasing the amount of self-serve tasks while facilitating a journey where people can stop and continue seamlessly.

Typography — Font Variants

Modern (default) .modern

Plus Jakarta Sans. Default site typeface. Applied by the font switcher when "modern" is selected.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html (via font switcher)

The future is conversational — when it works.

Serif .serif

TNY Adobe Caslon Pro Regular. Elegant classic serif, offered as an alternative reading style.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html (via font switcher)

The future is conversational — when it works.

Sans-serif (Accessible) .sans-serif

Atkinson Hyperlegible. Dyslexia-friendly typeface. The accessibility-focused reading option.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html (via font switcher)

The future is conversational — when it works.

Typography — Text Utilities

Highlight .highlights

Inline yellow highlight (light mode) / blue (dark mode). Wraps key words or phrases for emphasis.

Used on: index.html, about.html, contacts.html, all project pages

A generalist with a soft spot for complex systems.

Grey / Muted .grey

Muted text colour (var(--text-color-grey)). Used for secondary or supporting text.

Used on: All pages with secondary text

Primary text. Secondary muted text alongside it.

Subtitle .subtitle

32px / weight 500, letter-spacing -1px. Used directly under hero headings.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html

When a conversational interface helps.

Typography — Paragraph Quote

Paragraph Quote .paragraph-quote

Inline block-quote style for pull quotes inside article body text. Left border (2px, var(--input-border)) with 48px left padding. Used as a <p> containing <i>-wrapped quote text, followed by a <p><small> attribution line.

Used on: what_ai_exposes.html, AI_tracking_for_elderly_people.html

"The self-serving bias rules many situations, but, surprisingly, it doesn't work when it comes to computers and applications!"

Lucy Adams, Why Users Blame Themselves for Designers' Mistakes

Buttons & Links — Primary Button

Primary (Dark) Button .btn.btn-dark.btn--arrowed

Main CTA button with animated SVG arrow. Hover animates the arrow right and darkens the background.

Used on: index.html, about.html, contacts.html, all project pages

Buttons & Links — Nav Links

Nav Link .navtrans

Navigation menu items. Weight 600, 0.4s transition. Active/hover state: bold, colour #196AE3. Used with a direction icon (/repository/img/Right.svg or Left.svg).

Used on: All pages (in navbar)

Buttons & Links — Back Navigation

Go Back Link .navtrans.goback

End-of-article back navigation link. Combines .navtrans (nav transition behaviour) with .goback (padding-top 6%, cursor pointer). Placed after the last .article block, inside the .col-lg-12 wrapper. Uses ‹ Back to articles with blue colour.

Used on: what_ai_exposes.html, AI_tracking_for_elderly_people.html

Chips & Badges — Status

Chip (New) .chip

Green badge. Marks new content or features.

Used on: index.html, thoughts.html

New
Chip Alert (WIP / Concept) .chip-alert

Yellow badge. Marks work in progress or conceptual content.

Used on: index.html, thoughts.html, about.html

Concept Work in Progress
Changelog Labels .feature   .improve   .bug

Three labels for the site changelog. Blue = new feature. Pink = improvement. Yellow = bug fix.

Used on: about.html

Brand New Improved Bug Fixed

Chips & Badges — Font Chips

Font Chip (unselected / active) .font-chip   .font-chip.active

Toggle button used in the font and font-size switcher. Shows a plus icon when unselected, a checkmark when active. Border turns blue when selected.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html, what_ai_exposes.html, AI_tracking_for_elderly_people.html

Navigation — Dark Mode Toggle

Dark Mode Toggle .toggle-switch   .slider   .darkmode

Custom checkbox toggle in the navbar. Blue pill knob slides right when checked. Moon icon visible in unchecked state. Persists preference to localStorage.

Used on: All pages

Dark Mode

Navigation — Scroll Progress Bar

Scroll Progress Bar .scroll-line

4px teal line at the very top of the navbar. Width is set dynamically via JS (0–100%) as the user scrolls.

Used on: All pages

← 65% scrolled (example)

Layout & Sections — Article Page Layout

Article Page Shell .top-shape   .title-space

.top-shape is the outermost <section> for article pages: 90vw, centred with auto margins (max 1800px on very wide screens). Inside it, a .col-lg-10.offset-lg-1 column contains a .container-fluid > .row.title-space which provides 20% top margin. The row holds alternating .article.article-content text blocks and <section class="reveal"> image blocks as siblings.

Used on: what_ai_exposes.html, AI_tracking_for_elderly_people.html

<section class="top-shape"> <div class="col-lg-10 offset-lg-1"> <div class="container-fluid"> <div class="row title-space"> <!-- title block --> <section class="reveal"><!-- cover image --></section> <div class="col-lg-12"><div class="article article-content">…</div></div> <section class="reveal"><!-- inline image --></section> <div class="col-lg-12"><div class="article article-content">…</div></div> </div> </div> </div> </section>
Article Text Constraint .article

Constrains long-form body text to a max-width of 700px at ≥992px viewport, 100% at smaller screens. Always paired with .article-content on the same element. Images are placed outside this div (as <section class="reveal"> siblings) so they can span the full column width.

Used on: what_ai_exposes.html, AI_tracking_for_elderly_people.html

This paragraph is constrained to 700px on large screens. Images sit outside this div as siblings in the row, allowing them to span the full column width.

Layout & Sections — Case Hero

Case Hero .case-hero

Full-bleed hero header for case studies. Centred text, 8rem top padding. Animates in via fadeInUp (paused until body.loaded). h1 and .subtitle also fade in with staggered delays. Includes a JS-driven parallax scroll effect.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html

The Future is Conversational

(when it works)

When a conversational interface helps, and when it doesn't.

Layout & Sections — Case Study Sections

Case Intro .case-intro

Wider wrapper (max-width 1200px) for hero area and leading image at the top of a case study page.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html

max-width: 1200px — contains .case-hero and opening media
Case Study .case-study

Narrower wrapper (max-width 860px) for the body content of a case study. Contains one or more .case-content articles.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html

max-width: 860px — main body container

Layout & Sections — Article Content

Article Content Section .article-content

A div wrapping a chunk of article text. Receives font-size modifier classes (.font-size-normal/medium/large) from the font-size switcher. On article pages, always also carries .article to apply the 700px max-width constraint.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html, what_ai_exposes.html, AI_tracking_for_elderly_people.html

The hypothesis

In 2019, we prototyped a chatbot for an automotive eCommerce platform. The assumption: conversational UI would reduce friction in complex vehicle discovery and quoting tasks.

Layout & Sections — Article List

Article Bullet List .ul-art

Used for bullet lists inside article body text. Restores indentation (padding-left: 24px) and disc bullets (list-style: disc !important) overriding the global body padding reset. Place inside .article.article-content. Font size is inherited from the font-size switcher via the li selector in typography.css.

Used on: what_ai_exposes.html

  • Continuous Discovery — an ongoing practice of learning about customers through frequent interaction.
  • Parallel Research Stream — research runs in parallel with design/development streams.

Layout & Sections — Notes Box

Notes / Highlight Box .notes

A paragraph with a coloured background (var(--highlights)) and 16px padding. Used for disclaimers or important callouts at the start of a section.

Used on: Ecosystem_V2.html

Before we start: I will talk about multiple systems, but I can only show the consumer-facing ones.

Layout & Sections — Keywords

Keywords .keywords

End-of-article tag strip. Muted text, 0.95rem, separated by a top border. Lists thematic keywords for the piece.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html

Keywords: User Experience | AI · Conversational UI | Behavioural Design | Concept Testing | Service Design

Layout & Sections — Wiseness Box

Wiseness Box .wiseness

A gradient-background container (light → slightly darker, via CSS vars). Used on the About page to wrap a featured content block.

Used on: about.html

What I've done and what I do.

Content inside a wiseness box with gradient background.

Media — Images

Responsive Image .img-responsive

block, max-width 100%, height auto. The default wrapper for all images.

Used on: All pages

Logo
Article Page Image .img-responsive.projectpics

Full-width image used inside <section class="reveal"> blocks on article pages. .projectpics sets max-width: 100% and zero padding; on screens ≤768px it constrains to 90% width with 5% margin. Always paired with .img-responsive. The wrapping <section class="reveal"> sits outside the .article div so images span the full column, not the 700px text width.

Used on: what_ai_exposes.html, AI_tracking_for_elderly_people.html

Example article image
Lightbox Trigger .lightbox-trigger

Added alongside .img-responsive. Changes cursor to zoom-in. Paired with onclick="openLightbox(this.src, this.alt)".

Used on: conversational_v2.html, Ecosystem_V2.html

Example image Hover — cursor becomes zoom-in. Click — opens lightbox.

Media — Video

Styled Video .videoz

max-width 100%, border-radius 24px, 8px border in light grey. Used for autoplay looping demo videos. Always includes playsinline muted autoplay loop attributes.

Used on: conversational_v2.html, Ecosystem_V2.html

.videoz — border-radius 24px, 8px solid #E9EDF1 border

Controls — Font Controls

Font Controls Panel .font-controls-wrapper   .font-control-section   .font-chip-group

Two-column panel at the top of article pages. Left section: font family switcher (Modern / Serif / Accessible). Right section: font size switcher (Normal / Medium / Large). Separated by a 1px vertical line on wider screens. Font family JS applies the chosen class to all p, li, and .link-text elements; font size JS adds .font-size-normal/medium/large to all .article-content elements.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html, what_ai_exposes.html, AI_tracking_for_elderly_people.html

Alternative Fonts:
Font Size:

Controls — Text-to-Speech

TTS Floating Button .speech-button   #speakBtn

Floating "Listen" button fixed at bottom-right of the page. Triggers Web Speech API on the page's article content. Activates a collapsed drawer with speed, voice, and playback controls.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html

TTS Controls (Pause / Stop / Speed / Voice) .tts-controls   .control-group   .speech-button

Expanded drawer with pause, stop, speed (range), and voice (select) controls. Pause has a yellow hover; stop has a red hover. Active read-aloud text gets a green .tts-highlight.

Used on: conversational_v2.html, Ecosystem_V2.html, project_template.html

1.0×

Animations — Reveal on Scroll

Reveal .reveal   .reveal.visible

Elements start opacity 0 / translateY(20px). When scrolled into view, JS adds .visible → opacity 1 / translateY(0) over 1s. 2nd, 3rd and 4th siblings get staggered delays (0.1s–0.3s). Used as a wrapper around almost every content section.

Used on: All pages

.reveal.visible — fully shown (scroll trigger fired)
.reveal — initially hidden (opacity 0)