07 — UI & Components
UI & Components
A complete developer reference — design tokens, component CSS, and interaction states. Copy the token block into your global stylesheet and use the component snippets as the starting point for every UI element.
Design Tokens
Paste this block at the top of your global stylesheet. Reference these variables throughout — never hardcode hex values in component styles.
:root {
/* ── Brand Colours ── */
--color-brand-dark: #021300; /* primary text, borders, button bg */
--color-brand-green: #0AAD0A; /* hover, active, accent */
--color-brand-hover: #0E491F; /* deep hover (use sparingly) */
--color-white: #FFFFFF;
--color-surface: #F9FAFB; /* subtle backgrounds */
--color-border-light: #E5E7EB; /* dividers, non-featured borders */
/* ── Typography ── */
--font-family: 'Poppins', system-ui, sans-serif;
--font-weight-extrabold: 800;
--font-weight-bold: 700;
--font-weight-semibold: 600;
--font-weight-medium: 500;
--font-weight-regular: 400;
--font-weight-light: 300;
/* ── Spacing ── */
--spacing-section-sm: 4rem;
--spacing-section-lg: 6rem;
--spacing-header-gap: 3rem;
--spacing-subtext-gap: 1.5rem;
/* ── Radii ── */
--radius-card: 12px;
--radius-button: 6px;
--radius-input: 6px;
--radius-pill: 20px;
/* ── Transitions ── */
--transition-base: 0.2s ease;
} Buttons
Two variants only. Height is always 44px. Font weight 500. Border-radius 6px.
Defaultbg #021300, text white
Hoverbg #0AAD0A
Focusoutline: 2px solid #0AAD0A
Activebg #0AAD0A
Disabledopacity 0.4, pointer-events: none
.btn-primary {
display: inline-flex;
align-items: center;
justify-content: center;
height: 44px;
padding: 0 1.5rem;
font-family: var(--font-family);
font-size: 1rem;
font-weight: 500;
line-height: 1;
color: #ffffff;
background-color: var(--color-brand-dark);
border: none;
border-radius: var(--radius-button);
cursor: pointer;
text-decoration: none;
transition: background-color var(--transition-base);
}
.btn-primary:hover { background-color: var(--color-brand-green); }
.btn-primary:focus-visible { outline: 2px solid var(--color-brand-green); outline-offset: 2px; }
.btn-primary:active { background-color: var(--color-brand-green); }
.btn-primary:disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; } .btn-secondary {
display: inline-flex;
align-items: center;
justify-content: center;
height: 44px;
padding: 0 1.5rem;
font-family: var(--font-family);
font-size: 1rem;
font-weight: 500;
line-height: 1;
color: var(--color-brand-dark);
background-color: transparent;
border: 1px solid var(--color-brand-dark);
border-radius: var(--radius-button);
cursor: pointer;
text-decoration: none;
transition: all var(--transition-base);
}
.btn-secondary:hover { background-color: var(--color-brand-green); color: #fff; border-color: var(--color-brand-green); }
.btn-secondary:focus-visible { outline: 2px solid var(--color-brand-green); outline-offset: 2px; }
.btn-secondary:disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; } Venue / Listing Card
2px dark border, 12px radius, lifts on hover with green border.
Stoke Village Hall
.card {
background-color: var(--color-white);
border: 2px solid var(--color-brand-dark);
border-radius: var(--radius-card);
overflow: hidden;
display: flex;
flex-direction: column;
transition: border-color var(--transition-base), transform var(--transition-base);
}
.card:hover {
border-color: var(--color-brand-green);
transform: translateY(-2px);
}
.card__image { width: 100%; height: 240px; object-fit: cover; display: block; margin-bottom: 1rem; }
.card__title { font-weight: 700; font-size: 1.1rem; color: var(--color-brand-dark); line-height: 1.2; }
.card__meta { font-weight: 300; font-size: 14px; color: var(--color-brand-dark); margin-top: 0.25rem; } Search & Form Inputs
Dark border at rest, green border on focus with subtle glow.
.input {
width: 100%;
height: 44px;
padding: 0 1rem;
font-family: var(--font-family);
font-size: 1rem;
font-weight: 500;
color: var(--color-brand-dark);
background-color: var(--color-white);
border: 1px solid var(--color-brand-dark);
border-radius: var(--radius-input);
outline: none;
transition: border-color var(--transition-base), box-shadow var(--transition-base);
}
.input::placeholder { color: var(--color-brand-dark); opacity: 0.45; font-weight: 400; }
.input:hover { border-color: var(--color-brand-green); }
.input:focus {
border-color: var(--color-brand-green);
box-shadow: 0 0 0 3px rgba(10, 173, 10, 0.08);
} Focus & Accessibility
Brand focus rings apply to keyboard navigation only — they are suppressed on mouse click.
/* Brand focus ring — keyboard only */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible {
outline: 2px solid var(--color-brand-green);
outline-offset: 2px;
}
/* Suppress on mouse click */
a:focus:not(:focus-visible),
button:focus:not(:focus-visible),
input:focus:not(:focus-visible) {
outline: none;
box-shadow: none;
} Section Layout Pattern
Every content section follows the same structural pattern.
H2 · 800 ExtraBold · #021300
↕ 1.5rem
Subtext · 300 Light · #021300 · max-width 36rem
↕ 3rem
Content — cards / grid / list
.section { padding: 4rem 1.5rem; }
@media (min-width: 1024px) { .section { padding: 6rem 2rem; } }
.section__heading {
font-size: clamp(2rem, 3vw, 3rem);
font-weight: 800;
color: var(--color-brand-dark);
letter-spacing: -0.02em;
line-height: 1.1;
margin-bottom: 1.5rem;
}
.section__subtext {
font-size: 1rem;
font-weight: 300;
color: var(--color-brand-dark);
line-height: 1.625;
max-width: 36rem;
margin-bottom: 3rem;
}