Layout tree (as in design/layout.json)
{
"pattern": "features.neobrutal-shadow-cards",
"kind": "features",
"grid": {
"header": "1-12",
"cards": "1-12"
},
"slots": [
"title",
"sectionLabel",
"features[4..6]"
],
"notes": "Two columns, never three. Each card: 3px border, radius token, hard shadow; the square is accent on every card.",
"tree": {
"el": "box",
"gap": 6,
"children": [
{
"el": "box",
"mobile": "keep",
"dir": "row",
"gap": 3,
"align": "end",
"justify": "between",
"wrap": true,
"children": [
{
"el": "text",
"slot": "title",
"role": "h2",
"step": 4,
"maxCh": 18
},
{
"el": "text",
"bg": "accent2",
"color": "onAccent2",
"slot": "sectionLabel",
"role": "label",
"weight": 700,
"rotate": 3
}
]
},
{
"el": "repeat",
"slot": "features",
"min": 4,
"max": 6,
"layout": "grid",
"cols": 2,
"gap": 4,
"of": {
"el": "box",
"bg": "surface",
"gap": 2,
"pad": [
4,
4
],
"border": "all",
"children": [
{
"el": "box",
"mobile": "keep",
"dir": "row",
"gap": 2,
"align": "center",
"children": [
{
"el": "shape",
"kind": "square",
"size": "sm",
"fill": "accent"
},
{
"el": "text",
"slot": "number",
"role": "label",
"font": "mono"
}
]
},
{
"el": "text",
"slot": "title",
"role": "h3"
},
{
"el": "text",
"slot": "body",
"role": "body",
"maxCh": 48
}
]
}
}
]
}
}Component example: reference/features.neobrutal-shadow-cards.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>features.neobrutal-shadow-cards — Neo-Brutalism</title>
<link rel="stylesheet" href="base.css">
<style>
section { padding: calc(var(--unit) * 14) 0; }
.head { display: flex; justify-content: space-between; align-items: end; gap: calc(var(--unit) * 3); flex-wrap: wrap; margin-bottom: calc(var(--unit) * 6); }
.head h2 { font-size: var(--step-4); max-width: 18ch; }
.head .sticker { transform: rotate(3deg); }
.cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: calc(var(--unit) * 4); }
.card { padding: calc(var(--unit) * 4); display: grid; gap: calc(var(--unit) * 2); align-content: start; }
.card .tag { display: flex; align-items: center; gap: calc(var(--unit) * 2); }
.card .sq { width: 20px; height: 20px; background: var(--accent); border: var(--bw) solid var(--border); }
.card h3 { font-size: var(--step-2); }
.card p { max-width: 48ch; }
@media (max-width: 640px) { .cards { grid-template-columns: 1fr; } .head h2 { font-size: var(--step-3); } }
</style>
</head>
<body>
<section class="wrap">
<div class="head"><h2>Everything an invoice should do</h2><span class="sticker label">4 things, no fluff</span></div>
<div class="cards">
<article class="card box"><p class="tag"><span class="sq"></span><span class="mono">01</span></p><h3>Pay links</h3><p>Every invoice is a link. Clients pay by card, bank or wallet without making an account.</p></article>
<article class="card box"><p class="tag"><span class="sq"></span><span class="mono">02</span></p><h3>Polite reminders</h3><p>Three nudges, spaced out and written like a human. You choose the tone; we send them.</p></article>
<article class="card box"><p class="tag"><span class="sq"></span><span class="mono">03</span></p><h3>Tax that adds up</h3><p>VAT, GST and sales tax worked out per client, per country, with receipts your accountant likes.</p></article>
<article class="card box"><p class="tag"><span class="sq"></span><span class="mono">04</span></p><h3>Payouts in a day</h3><p>Money lands in your account the next working day. No holds, no surprise fees.</p></article>
</div>
</section>
</body>
</html>