Styling
The theme uses a combination of Tailwind CSS, design tokens, component SCSS, and global SCSS.
Design Tokens
Design tokens are the foundation of the visual system. They're defined in tailwind/config/ and wired into Tailwind via custom plugins in tailwind/.
| Token category | Config file | Plugin |
|---|---|---|
| Colors | tailwind/config/colors.js | tailwind/colors.js |
| Typography | tailwind/config/typography.js | tailwind/typography.js |
| Spacing | tailwind/config/spacing.js | tailwind/spacing.js |
| Grid | tailwind/config/grid.js | tailwind/grid.js |
| Radius | tailwind/config/radius.js | (via tailwind.config.js) |
Colors
Colors are semantic — use token names, not raw values:
<!-- Good -->
<div class="bg-bgPrimary text-textPrimary border-shadeMedium">
<!-- Bad -->
<div class="bg-white text-black border-gray-300">Key semantic tokens: bgPrimary, bgSecondary, textPrimary, textSecondary, signalPrimary, buttonPrimaryContrast, buttonPrimaryHover.
There is a single neutral theme with tokens output on :root. No dark: mode is configured. For a dark band, use explicit utilities (e.g., bg-textPrimary text-bgPrimary).
Typography
Use the typography plugin classes instead of raw Tailwind font utilities:
<h2 class="ll-display-lg">Headline</h2>
<p class="ll-body-md">Body text</p>
<span class="ll-label-sm">Label</span>
<a class="ll-button-md">Button text</a>Categories: ll-display-*, ll-heading-*, ll-body-*, ll-label-*, ll-button-*, ll-add-tag, ll-font-quote.
WARNING
Do not use legacy ll-font--* classes.
Spacing
Use the token scale from the spacing plugin:
<div class="p-md mt-lg gap-sm py-section-md">Spacing tokens use fluid values that scale between screenMin and screenMax. Avoid raw Tailwind spacing numbers unless they match the token scale.
Radius
Use keys from the radius config:
<div class="rounded-md">
<button class="rounded-button">Custom Breakpoints
screens: {
xs: '400px',
sm: '600px',
md: '800px',
lg: '1000px',
xl: '1200px',
'2xl': '1440px',
// Max-width (negative) breakpoints
'-xl': { max: '1199px' },
'-lg': { max: '999px' },
'-md': { max: '799px' },
'-sm': { max: '599px' },
'-xs': { max: '399px' },
}Negative breakpoints use a minus prefix: -lg:hidden means hidden below 1000px.
File Structure
src/scss/
styles.scss ← Entry: Tailwind layers + global partials
base/
_theme.scss ← :root surface + text defaults
fonts.scss ← @font-face declarations
forms.scss ← Form element defaults
cookiebot.scss ← Cookiebot overrides
scroll.scss ← Scroll behavior
sections/
general.scss ← .ll-container, .ll-section, .ll-grid
header.scss ← Header-specific styles
tailwind/
config/ ← Token source of truth
colors.js ← llColors plugin
typography.js ← llTypography plugin
spacing.js ← llSpacing plugin
grid.js ← llGrid plugin
components/
sections/**/style.scss ← Component-scoped styles
blocks/**/style.scss
parts/**/style.scssGlobal vs Component Styles
- Global styles live in
src/scss/and are imported viasrc/scss/styles.scss - Component styles live alongside their Liquid files as
style.scssand are eagerly imported viasrc/js/styles.js
Layout Utilities
| Class | Purpose |
|---|---|
ll-container | Centered content container with max-width |
ll-section | Section wrapper with vertical padding |
ll-grid | Grid system with token-based columns and gutters |
CSS Class Naming
| Prefix | Purpose | Example |
|---|---|---|
ll- | Layout utilities and design system | ll-container, ll-body-md |
js- | JavaScript DOM selection only | js-slider, js-button |
DANGER
Never use js- prefixed classes for styling. Never use style classes for JS selection.
Example
<section class="ll-section">
<div class="ll-container py-section-md">
<h2 class="ll-heading-2 text-textPrimary">{{ title }}</h2>
<p class="ll-body-md text-textSecondary mt-md">{{ text }}</p>
</div>
</section>Using @apply
Use @apply sparingly in component SCSS — only when Tailwind utilities can't be applied in markup. Prefer semantic utilities in Liquid for colors and spacing.