<link rel="stylesheet" href="tea-styles.css"> – then copy the markup
under any component below (click Show / Copy code). Re-theme the entire system by editing the
tokens at the top of tea-styles.css. House style: rounded corners, soft
shadows, WCAG-AA contrast, underline-on-hover for all text links.
Colour tokens
Blue is the lead colour, green the accent, with a gradient between them. Edit the tokens in :root to re-skin everything.
Note: the *-soft tints are background fills only (badges, hovers, section washes) – they are not accent colours and shouldn't carry meaning on their own.
Typography
Headings in Spline Sans Semibold, body in Helvetica Neue. Use the .tea-h1…h6, .tea-body, .tea-small classes.
<h1 class="tea-h1">Heading</h1> <p class="tea-lead">Intro lead paragraph.</p> <p class="tea-body">Body copy.</p> <a href="#" class="link">Text link</a>
Shadows & radius
One universal drop shadow (--tea-shadow) is applied to every card and floating surface – soft, generous, low opacity, sitting between the old medium and large. Paired with a 1px grey outline. Three corner radii only: small, medium, pill (cards use a fixed 20px).
/* One shadow everywhere */ box-shadow: var(--tea-shadow); border: 1px solid var(--tea-line); border-radius: var(--tea-radius-card); /* cards */ /* Radii: --tea-radius-sm | --tea-radius-md | --tea-radius-pill */
Buttons
Variants, sizes, states. Icons sit inline with .icon.
<button class="btn">Primary (blue)</button>
<button class="btn btn--accent">Accent (green)</button>
<button class="btn btn--gradient">Gradient</button>
<button class="btn btn--secondary">Secondary</button>
<button class="btn btn--ghost">Ghost</button>
<button class="btn btn--danger">Danger</button>
<button class="btn btn--sm">Small</button>
<button class="btn btn--lg btn--pill">Large pill</button>
<button class="btn" disabled>Disabled</button>
<!-- Button with trailing right arrow (CTA) -->
<button class="btn">Get started
<svg class="icon icon--arrow" viewBox="0 0 24 24" stroke-width="2">
<path d="M5 12h14M13 6l6 6-6 6"/></svg>
</button>
Labels & badges (pills)
Pill-shaped labels for categories/tags, plus status badges.
<span class="label">Strategy</span> <span class="label label--outline">Development</span> <span class="label label--neutral">Filter <span class="label__x">×</span></span> <span class="badge badge--success badge--dot">Success</span>
Cards
With image, without image, overlay, horizontal, and stat – shown in 3- and 4-column grids.
3-column · image cards
Overlay card
Text sits over the image with a gradient scrim.
<div class="tea-grid tea-grid--3">
<article class="card card--interactive">
<img class="card__media" src="…" alt="">
<div class="card__body">
<div class="card__tags"><span class="label">Insight</span></div>
<div class="meta-item tea-small"><svg class="icon">…cal…</svg> 15 May 2026</div>
<h3 class="card__title">Title</h3>
<p class="card__text">Supporting line.</p>
<a href="#" class="link">Read more</a>
</div>
</article>
</div>
<!-- Overlay: <article class="card card--overlay"> -->
3-column · category badge on image (top-right)
<article class="card card--interactive">
<div class="card__media">
<img src="…" alt="">
<span class="label label--solid card__badge">Insight</span> <!-- top-right -->
</div>
<div class="card__body">
<span class="card__date"><svg class="icon">…</svg> 15 May 2026</span>
<h3 class="card__title">Title</h3>
<p class="card__text">Supporting line.</p>
<a href="#" class="link">Read more</a>
</div>
</article>
4-column · no-image & stat cards
No-image card
Icon-led card for services or features.
Flexible
Mix and match across grids.
<div class="tea-grid tea-grid--4">
<article class="card card--plain">
<div class="card__body">
<div class="card__icon"><svg class="icon icon--lg">…</svg></div>
<h3 class="card__title">Title</h3>
<p class="card__text">Text.</p>
</div>
</article>
<article class="card card--stat card--plain">
<div class="card__body">
<div class="stat__value">98%</div>
<div class="stat__label">Retention</div>
</div>
</article>
</div>
Horizontal card
<article class="card card--horizontal"> <img class="card__media" src="…" alt=""> <div class="card__body">…</div> </article>
Icon cards (no image)
<div class="tea-grid tea-grid--3">
<article class="card card--icon card--interactive">
<div class="card__body">
<div class="card__icon"><svg>…</svg></div>
<h3 class="card__title">Brand strategy</h3>
<p class="card__text">One-line description.</p>
<a href="#" class="link">Learn more</a>
</div>
</article>
</div>
Truncated text (line clamp)
For uneven content lengths, clamp the title to one line and the body to a fixed number of lines — overflow is cut with an ellipsis so card heights stay even.
Building an ethical brand that genuinely lasts the distance
An ethical brand isn't a campaign or a colour palette — it's the sum of the decisions a business makes when no one is watching, day after day.
Read moreA short title
A much longer supporting paragraph that runs well beyond two lines so you can see exactly where the clamp cuts it off and adds the trailing ellipsis at the end.
Read moreAnnual impact & sustainability report 2026 — full edition
The complete report. This description is deliberately long to demonstrate three-line and two-line clamping behaviour across cards of differing content.
Open PDF<!-- single-line title, ellipsis --> <h3 class="card__title truncate">Very long title…</h3> <!-- clamp body to N lines: clamp-1 / clamp-2 / clamp-3 --> <p class="card__text clamp-2">Long description…</p>
Event card
Full-bleed banner image (no text baked over it), then a bold title, a one-line description, and an icon-meta list for date and venue. Uses the universal 1px outline + soft card shadow.
GreenBiz
The premier annual gathering for sustainable business leaders.
<article class="card event-card">
<!-- Full-bleed banner: image spans the whole card width -->
<img class="card__media" src="event-banner.jpg" alt="GreenBiz 27">
<div class="card__body">
<h3 class="event-card__title">GreenBiz</h3>
<p class="card__text">The premier annual gathering for sustainable business leaders.</p>
<div class="meta-list">
<div class="meta-item">
<svg class="icon">…calendar…</svg> Feb 23, 2027 – Feb 25, 2027
</div>
<div class="meta-item">
<svg class="icon">…building…</svg> Gaylord Pacific, San Diego
</div>
</div>
</div>
</article>
Content rows
Alternating media + text rows – image left, then image right directly underneath. Each has a heading, body copy and a text link. Stacks to one column on mobile.
Image left, content right
A short paragraph of body copy describing the section. Use these rows for services, features or alternating story blocks down a page.
Learn moreImage right, content left
The reverse modifier flips the layout so rows alternate down the page. Keep copy concise and lead with a clear text link.
Learn more<div class="content-row">
<img class="content-row__media" src="…" alt="">
<div class="content-row__body">
<span class="label">Strategy</span>
<h3 class="content-row__title">Heading</h3>
<p class="content-row__text">Body copy.</p>
<a href="#" class="link">Learn more</a>
</div>
</div>
<!-- image on the right: add --reverse -->
<div class="content-row content-row--reverse">…</div>
Tabs
Underline tabs and pill tabs. Toggle with the small script included in this page.
<div class="tabs" role="tablist"> <button class="tabs__tab" role="tab" aria-selected="true">Overview</button> <button class="tabs__tab" role="tab" aria-selected="false">Details</button> </div> <div class="tabs__panel">…</div> <!-- Pills: <div class="tabs--pills"> --> <!-- Connected/bleed tabs: --> <div class="tabs--bleed"> <button class="tabs__tab" aria-selected="true">Tab</button> </div> <div class="tabs__panel--bleed">…content…</div>
FAQ accordion
Native <details> – no JS required. Two-column layout collapses to one column on mobile.
What does TEA stand for?
Do you work internationally?
How do we start a project?
What services do you offer?
How long does a project take?
Do you offer ongoing support?
<div class="tea-grid tea-grid--2">
<div class="faq">
<details class="faq__item" open>
<summary>Question?</summary>
<div class="faq__answer">Answer text.</div>
</details>
</div>
<div class="faq">…second column…</div>
</div>
Form elements
Inputs, select, textarea, checkbox, radio, toggle, plus validation states.
<div class="field"> <label class="field-label">Name</label> <input class="input" placeholder="Jane Doe"> </div> <select class="select">…</select> <textarea class="textarea"></textarea> <label class="check"><input type="checkbox"> Label</label> <label class="switch"><input type="checkbox"><span class="switch__track"></span> Toggle</label> <!-- States: .is-invalid / .is-valid + .error-text -->
Contact form
A ready-to-use composed block. Required fields marked with *.
<form class="contact-form">
<h3 class="tea-h3">Get in touch</h3>
<div class="form-row">
<div class="field"><label class="field-label">First name *</label><input class="input"></div>
<div class="field"><label class="field-label">Last name *</label><input class="input"></div>
</div>
<div class="field"><label class="field-label">Message *</label><textarea class="textarea"></textarea></div>
<button class="btn btn--block btn--lg">Send message</button>
</form>
Resources – search & filter
Live demo: search plus two dropdown filters – Category and Region. Wired with the script at the bottom of this page.
Building an ethical brand
ReadWeb accessibility guide
ReadBrand toolkit
Open PDFMeasuring campaign impact
ReadContent strategy playbook
ReadAnnual impact report
Open PDF<div class="toolbar">
<div class="search">
<svg class="icon">…search…</svg>
<input class="input" id="resSearch" placeholder="Search resources…">
</div>
<div class="filters">
<select class="select" id="resCategory">…All categories / Articles / Guides / PDFs…</select>
<select class="select" id="resRegion">…All regions / Cape Town / London / Global…</select>
</div>
</div>
<div class="tea-grid tea-grid--3" id="resGrid">
<article class="card" data-type="pdf" data-region="global" data-title="Brand toolkit">…</article>
</div>
<!-- JS filters by data-type (Category) + data-region (Region) + search -->
Alerts
<div class="alert alert--success"> <div><div class="alert__title">Saved</div>Message text.</div> </div>
Table
| Project | Client | Status |
|---|---|---|
| Rebrand | Acme Co | Live |
| Website | Beta Ltd | In progress |
| Campaign | Gamma | Planned |
<table class="table table--bordered"> <thead><tr><th>Project</th></tr></thead> <tbody><tr><td>Rebrand</td></tr></tbody> </table>
Breadcrumbs & pagination
Modal · tooltip · progress
<div class="progress"><div class="progress__bar" style="width:62%"></div></div> <div class="spinner"></div> <span class="tooltip" data-tip="Tip text">Hover me</span> <span class="avatar">TE</span> <!-- Modal markup: .modal-overlay > .modal -->
Popup
A centred dialog – icon, title, body and a CTA button. Uses the shared .modal-overlay backdrop.
<div class="modal-overlay">
<div class="popup">
<button class="popup__close">×</button>
<div class="popup__icon"><svg>…</svg></div>
<h3 class="popup__title">Title</h3>
<p class="popup__body">Body copy.</p>
<button class="btn btn--block btn--lg">Call to action</button>
</div>
</div>
Stats counter row
Big animated counters with labels. Numbers count up when the row scrolls into view.
<div class="stats-row" data-stats>
<div class="stat-item">
<div class="stat-item__value" data-count="98" data-suffix="%">0</div>
<div class="stat-item__label">Client retention</div>
</div>
…
</div>
<!-- JS counts each value up to data-count when scrolled into view -->
CTA section
Full-width rounded call-to-action. With image (split) or without (centred). Each shows a button plus an optional text-link.
With image
Award-winning report designers – 400+ reports across 25 countries.
Trusted by UNDP, the World Bank, Greenpeace, B Lab Africa and more.
<div class="cta cta--split">
<img class="cta__media" src="…" alt="">
<div>
<span class="cta__eyebrow">Eyebrow</span>
<h3 class="cta__title">Headline</h3>
<p class="cta__text">Supporting line.</p>
<div class="cta__actions">
<button class="btn btn--lg">Primary action</button>
<a href="#" class="link">Text link</a>
</div>
</div>
</div>
Without image (centred, gradient)
Ready to build something worth being proud of?
Tell us what you're working on and we'll come back within two working days.
Ready to build something worth being proud of?
Tell us what you're working on and we'll come back within two working days.
<!-- --gradient = full brand gradient (white text) -->
<!-- --soft = blue-tint to green-tint, dark text -->
<div class="cta cta--center cta--gradient">
<span class="cta__eyebrow">Eyebrow</span>
<h3 class="cta__title">Headline</h3>
<p class="cta__text">Supporting line.</p>
<div class="cta__actions">
<button class="btn btn--secondary btn--lg">Primary action</button>
</div>
</div>
Quote / testimonial
A testimonial row with quote mark, attributed author and avatar.
TEA was contracted by GIZ to support the Presidency on the PYEI microsite and related design and marketing materials. The agency is agile and delivers high-quality products within tight timeframes – it has been a pleasure working with them.
<div class="quote">
<span class="quote__mark">“</span>
<p class="quote__text">Testimonial copy…</p>
<div class="quote__author">
<img class="quote__avatar" src="…" alt="">
<div>
<div class="quote__name">Name</div>
<div class="quote__role">Role, Company</div>
</div>
</div>
</div>
Feature quotes
Editorial pull-quote options for articles and landing pages.
Centred – rules top & bottom
"What is a scientist after all? It is a curious person looking through a keyhole, the keyhole of nature, trying to know what's going on."
Jacques-Yves Cousteau
<blockquote class="quote-feature"> <hr class="quote-feature__rule"> <p class="quote-feature__text">"Quote text…"</p> <cite class="quote-feature__cite">Attribution</cite> <hr class="quote-feature__rule"> </blockquote>
Centred – italic text, upright attribution
"What is a scientist after all? It is a curious person looking through a keyhole, the keyhole of nature, trying to know what's going on."
Jacques-Yves Cousteau
<!-- add --italic: text italic, attribution stays upright --> <blockquote class="quote-feature quote-feature--italic"> <hr class="quote-feature__rule"> <p class="quote-feature__text">"Quote text…"</p> <cite class="quote-feature__cite">Attribution</cite> <hr class="quote-feature__rule"> </blockquote>
Framed – corner brackets & quote marks
The deeds you do may be the only sermon some persons will hear today.
<figure class="quote-framed"> <span class="quote-framed__mark quote-framed__mark--open">“</span> <p class="quote-framed__text">Quote text…</p> <figcaption class="quote-framed__cite">– Attribution</figcaption> <span class="quote-framed__mark quote-framed__mark--close">“</span> <!-- rotated 180° via CSS --> </figure>
Logo carousel
Affiliations / client logos in white cards. Arrows scroll the row; hover pauses nothing – it's manual. Drag/scroll works too.
We've made a few friends along the way
<div class="logos">
<span class="logos__eyebrow">Affiliations</span>
<h3 class="logos__title">We've made a few friends</h3>
<div class="logos__row" id="logoRow">
<div class="logo-card"><img src="logo.svg" alt="…"></div>
…
</div>
<div class="logos__controls">
<button class="logos__nav" data-logo-prev>‹</button>
<div class="logos__dots">…</div>
<button class="logos__nav" data-logo-next>›</button>
</div>
</div>