Free for personal use, no card required.
Cancel anytime.
Get enterprise support, audit logs, and SSO.
42 architectural principles in one document.
Use when the surrounding flow is left-aligned content.
/*
* CTA — section
*
* Hero-lite: title + lede + actions, designed for mid-page conversion
* blocks ("Ready to start? Sign up.") rather than above-the-fold.
*
* <section class="cta">
* <h2 class="cta__title">Ready to start?</h2>
* <p class="cta__lede">Free for personal use, no card required.</p>
* <div class="cta__actions">
* <a class="button -primary">Sign up</a>
* <a class="button -ghost">Talk to sales</a>
* </div>
* </section>
*/
@layer malevich.components {
.cta {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
gap: var(--space-gap-elements-m);
padding-block: var(--space-inset-section-m);
padding-inline: var(--space-inset-section-m);
background-color: var(--color-surface-raised);
color: var(--color-ink-strong);
border-radius: var(--radius-section);
inline-size: 100%;
box-sizing: border-box;
}
.cta > * {
max-inline-size: var(--hero-max-content);
}
.cta__title {
margin: 0;
color: var(--color-ink-strong);
font-family: var(--font-display-statement-family);
font-size: var(--font-display-statement-size);
font-weight: var(--font-display-statement-weight);
line-height: var(--font-display-statement-line-height);
letter-spacing: var(--font-display-statement-letter-spacing);
}
.cta__lede {
margin: 0;
color: var(--color-ink-regular);
font-family: var(--font-body-regular-family);
font-size: var(--font-body-regular-size);
font-weight: var(--font-body-regular-weight);
line-height: var(--font-body-regular-line-height);
letter-spacing: var(--font-body-regular-letter-spacing);
}
.cta__actions {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
gap: var(--space-gap-elements-s);
margin-block-start: var(--space-gap-elements-s);
}
/* On-surface variants */
.cta.-on-accent {
background-color: var(--color-accent);
color: var(--color-ink-inverse);
}
.cta.-on-accent .cta__title,
.cta.-on-accent .cta__lede {
color: var(--color-ink-inverse);
}
.cta.-on-inverse {
background-color: var(--color-ink-strong);
color: var(--color-ink-inverse);
}
.cta.-on-inverse .cta__title,
.cta.-on-inverse .cta__lede {
color: var(--color-ink-inverse);
}
.cta.-bordered {
background-color: transparent;
border: var(--border-width-hairline) solid var(--color-border-default);
}
/* Left-aligned variant */
.cta.-start {
align-items: flex-start;
text-align: start;
}
.cta.-start .cta__actions {
justify-content: flex-start;
}
}
This component is pure CSS — no JavaScript required.
# Cta — AGENTS.md
> Auto-generated from `cta.docs.md` + the modifier applicability matrix.
> Edit those source files; this file regenerates on build.
## Identity
- **Component:** `cta`
- **Layer:** sections
- **Status:** stable
- **Last updated:** 2026-05-19
## Summary
- End-of-page conversion: "Ready to start?"
## Variants
| Variant | Class | Use for |
|-------------|----------------------|----------------------------------------|
| Default | `.cta` | Raised surface card, centered |
| On accent | `.cta.-on-accent` | Accent-colored block |
| On inverse | `.cta.-on-inverse` | Inverse (dark) block |
| Bordered | `.cta.-bordered` | Outlined, no fill |
| Start | `.cta.-start` | Left-aligned (override of centered) |
Variants compose: `.cta.-on-accent.-start`.
## Modifier applicability
Per ADR-0007. Modifiers attach via `data-{category}="value"` attributes.
| Category | Accepts |
|---|---|
| `background` | any value |
| `surface` | `flat`, `elevated` |
| `effect` | `grain`, `glow`, `ring` |
| `shader` | — |
| `rhythm` | `compact`, `regular`, `spacious` |
| `motion` | any value |
| `behavior` | — |
## Anatomy
```html
<section class="cta">
<h2 class="cta__title">Ready to start?</h2>
<p class="cta__lede">Free for personal use, no card required.</p>
<div class="cta__actions">
<a class="button -primary">Sign up</a>
<a class="button -ghost">Talk to sales</a>
</div>
</section>
<!-- Accent variant -->
<section class="cta -on-accent">
<h2 class="cta__title">Try Pro for 14 days.</h2>
<p class="cta__lede">Cancel anytime.</p>
<div class="cta__actions">
<a class="button -secondary">Start trial</a>
</div>
</section>
```
## Tokens consumed
### From semantic tier
- `--color-surface-raised` — default background
- `--color-accent` — on-accent
- `--color-ink-strong` — on-inverse + default text
- `--color-ink-regular` — lede text
- `--color-ink-inverse` — on-accent / on-inverse text
- `--color-border-default` — bordered variant
- `--space-inset-section-m` — padding
- `--space-gap-elements-{s,m}` — gaps
- `--radius-section` — corner radius
- `--border-width-hairline`
- `--font-display-statement-*`, `--font-body-regular-*`
### Component-tier (shared with Hero)
- `--hero-max-content` — measure cap
## Accessibility contract
- Use `<section>` for the wrapper so the block participates in document
outline.
- The title is an `<h2>` (or `<h3>` if the surrounding hierarchy is
deeper). Don't reuse `<h1>` here — that's Hero's job.
## Guidance
### Do
- Use Hero for the top of the page, CTA for everything else that asks
for action.
- Pair `.cta.-on-accent` with `.button.-secondary` so the button
reads as the "other" surface.
### Don't
- Don't stack two CTAs back-to-back. One conversion ask per section.
- Don't put more than 2 buttons in `.cta__actions` — the call dilutes.