# Djangify Content Blocks: the AI skill file

**About Djangify.** Djangify is a digital eCommerce Builder for creators who sell digital products and want to
own their shop. It includes checkout, delivery, customer accounts, a blog, info pages and SEO tools, with no
plugins and no per-sale cut. You can run it on managed hosting or self-host the whole codebase for one payment.
See the shop at https://www.djangify.com/shop/

**About this file.** This skill file teaches an AI assistant to turn plain article text into styled layout
blocks: tables, comparisons, checklists, steps, FAQs, galleries, video and more. It works with any AI
assistant, including ChatGPT, Claude, Gemini and Codex. Give the whole file to your AI along with your text,
then ask for a block by name.

**Read the full article** that shows every block in use, with a copyable prompt for each one:
https://www.djangify.com/blog/long-form-articles-seo-and-content-blocks/

**Download this file again:** https://www.djangify.com/media/public/products/previews/djangify-content-blocks.md

**See what else HTML can do.** Djangify info pages store HTML too, so a page can work like a small app. The
install guide is an example, with progress, Done ticks and copy buttons: https://www.djangify.com/docs/self-hosted-ecommerce-builder-install-guide/

Blocks are plain HTML plus one stylesheet. They run on a Djangify shop with no setup, and on any other website
that accepts HTML code once the stylesheet in Appendix A is added.

---

## How to use this file

The owner gives you a block name and some text, for example:
"Turn this into a Checklist block" or "Add a This vs That block comparing X and Y".

1. Find the block by name below.
2. Return only the HTML for that block, using the exact class names shown.
3. If the owner gives you a whole article, return the whole article HTML with the requested blocks placed
   where they fit. Keep the owner's wording. Do not rewrite their sentences unless asked.
4. If you have access to the Djangify MCP connector, update the post's `content` field directly.
   Otherwise return the HTML in one code block for the owner to paste into the editor's source code view.

## Rules that apply to every block

- Use only the classes listed here. Do not invent new class names or add inline styles.
- Never use `<script>`, `<style>` or `<svg>`. The editor removes them.
- Every `<img>` needs a meaningful `alt` that describes what is in the picture, plus `width` and `height`.
- Every H2 that a Contents List links to needs a matching `id`, written in lowercase with hyphens.
- Lightbox ids in an Image Gallery must be unique on the page (`cb-img-1`, `cb-img-2`, and so on).
- Shades come from the theme. Never write a hex value. In prompts, say "the primary theme shade".
- Keep each block short. Three or more blocks on one screen make the page feel busy.
- Writing rules for the owner's content still apply: American English, no em dashes, no emojis, no filler
  openers, and one clear point per section. Avoid words that differ between UK and US spelling.
- Say "shop", never "store".

## Where blocks work

Blocks work in every rich text area that is shown with the standard page styling (the `page-content` class):

- Blog posts: every theme and every content type.
- Info pages and policies. These build their own contents sidebar from H2 and H3 headings, so a Contents
  List is usually not needed there.
- Product pages: the description and the long description, in both the standard and landing layouts,
  including the fold-out description.
- Page sections: Hero, Text, Two Column, Two Column Text, Three Column, Content Blocks, Features, FAQ and CTA,
  plus the intro of a questionnaire. This is how a block is added to a homepage or a sales page.
- Shop page sections: the hero text, the section text, the intro text and the three-column text.
- The one-time offer page: the offer body.
- Topic cluster pages: the intro, the about this guide box, the definition, the why it matters text, every
  section body, and the product, download and reflection text.
- Hosted tool pages: the description and the more-info text.

These areas show HTML but do not carry the block styling: the Text with Video section, the newsletter intro,
the blog intro on the homepage and the dashboard messages. Put the block in a Text section near them instead.
Emails cannot use blocks at all, because email apps ignore the stylesheet.

## Using the blocks on a site that is not Djangify

The blocks are plain HTML plus one stylesheet, so any site that accepts HTML can use them (a WordPress Custom
HTML block, Ghost, Webflow, Shopify pages, hand-built sites).

1. Add the stylesheet from Appendix A once, as a `<link>` to a saved file or pasted into the site's own CSS.
   It starts with a short `:root` list of theme shades that can be changed to match the brand.
2. Wrap the article or page text in `<div class="page-content"> ... </div>`.
3. Paste the blocks. Optionally add the script from Appendix B so the Prompt Box Copy button works. Without
   it the text is still there for readers to select and copy.

Visual editors (TinyMCE, the WordPress block editor and similar) may delete tags or classes they do not allow
when a page is saved. Ask the owner to paste one block into a draft, save it, reopen it and confirm it
survived before building a whole article. If it did not, add blocks through the source or HTML view and avoid
re-saving in the visual view. If the site strips class names or the `<details>` tag, tell the owner which
blocks will not work.

## Interactive pages (optional)

A page can also include a small script, for example a step-by-step guide with Done ticks and a progress bar
saved in the browser. Visual editors remove scripts when a page is saved, so add and edit a page like this
through an AI assistant connected to the shop (the Djangify MCP connector) or directly in the database, not in
the visual editor. Never put a script inside a normal content block.

## Buttons

Link Row buttons use the accent shade with squared-off corners and a secondary hover. The Product Box button
is black with white text on the primary panel. Do not add pill-shaped or inline-styled buttons.

## Choosing blocks

Read the draft and ask what each section is.

| If the section is... | Use |
|---|---|
| A summary of the whole article | Key Takeaways |
| A list of sections to jump to | Contents List |
| Rows and columns of facts | Comparison Table |
| Two options side by side | This vs That |
| Two lists of bullets under one title | Two Lists |
| One or three big numbers | Facts Row |
| A tip, warning or single key point | Callout |
| A memorable sentence | Quote |
| Things to do in order | Numbered Steps |
| Things to tick off | Checklist |
| Text the reader should copy | Prompt Box |
| An old version and a new version | Before and After |
| Questions and answers | FAQ |
| Several pictures | Image Gallery |
| A YouTube video | Video |
| Links to follow | Link Row |
| Other posts to read | Featured Articles |
| A product or offer | Product Box |

Two or three blocks suit most articles. Long articles gain the most, but every block works in short posts and
on info pages too.

---

## 1. Key Takeaways

Use at the top of a long article, right after the introduction.

```html
<div class="cb-takeaways">
<span class="cb-label">Key takeaways</span>
<ul>
<li>First point.</li>
<li>Second point.</li>
<li>Third point.</li>
</ul>
</div>
```

## 2. Contents List

Use near the top of an article with four or more H2 sections. Each `href` matches an `id` on a heading.

```html
<div class="cb-toc">
<span class="cb-label">In this article</span>
<ol>
<li><a href="#first-section">First section title</a></li>
<li><a href="#second-section">Second section title</a></li>
</ol>
</div>

<h2 id="first-section">First section title</h2>
<h2 id="second-section">Second section title</h2>
```

## 3. Comparison Table

Use for rows and columns of facts. Keep cells short. It scrolls sideways on phones by itself.

```html
<div class="cb-table-wrap">
<table class="cb-table">
<caption>Short caption</caption>
<thead>
<tr><th scope="col">Item</th><th scope="col">Column A</th><th scope="col">Column B</th></tr>
</thead>
<tbody>
<tr><th scope="row">Row label</th><td>Value</td><td>Value</td></tr>
</tbody>
</table>
</div>
```

## 4. This vs That

Use for two options. Three to five short bullets per side.

```html
<div class="cb-compare">
<div class="cb-compare-col">
<h3>Option A</h3>
<ul>
<li>Point</li>
<li>Point</li>
</ul>
</div>
<div class="cb-compare-col cb-b">
<h3>Option B</h3>
<ul>
<li>Point</li>
<li>Point</li>
</ul>
</div>
</div>
```

## 5. Two Lists

Use for one title over two boxes of bullets, on a light background.

```html
<div class="cb-lists">
<h3>Section title</h3>
<div class="cb-lists-grid">
<div class="cb-list-box">
<h4>First list</h4>
<ul>
<li>Point</li>
<li>Point</li>
</ul>
</div>
<div class="cb-list-box cb-b">
<h4>Second list</h4>
<ul>
<li>Point</li>
<li>Point</li>
</ul>
</div>
</div>
</div>
```

## 6. Facts Row

Use for exactly three facts. The big text should be a number or one short word. The label is five words or fewer.

```html
<div class="cb-facts">
<div class="cb-fact"><strong>18</strong><span>Label</span></div>
<div class="cb-fact"><strong>0</strong><span>Label</span></div>
<div class="cb-fact"><strong>1</strong><span>Label</span></div>
</div>
```

## 7. Callout

Use for a tip, a warning or one key point. One short paragraph.

```html
<div class="cb-callout">
<span class="cb-label">Tip</span>
<p>The point, in one or two sentences.</p>
</div>
```

## 8. Quote

Use for a memorable sentence or a quotation. The source line is optional.

```html
<blockquote class="cb-quote">
<p>The quotation.</p>
<p class="cb-source">Name</p>
</blockquote>
```

## 9. Numbered Steps

Use for anything done in order. A bold title and one sentence per step.

```html
<ol class="cb-steps">
<li><strong>Step title</strong><span>One sentence of detail.</span></li>
<li><strong>Step title</strong><span>One sentence of detail.</span></li>
</ol>
```

## 10. Checklist

Use for things to tick off. The background is the primary theme shade. Ticking is visual only.

```html
<div class="cb-checklist">
<span class="cb-label">Label</span>
<h3>Checklist title</h3>
<ul>
<li><strong>Item</strong><span>Short detail.</span></li>
<li><strong>Item</strong><span>Short detail.</span></li>
</ul>
</div>
```

## 11. Prompt Box

Use for a prompt, command or code the reader should copy. The Copy button needs no setup.
Write `<` as `&lt;` and `&` as `&amp;` inside the `<pre>`.

```html
<div class="cb-prompt"><div class="cb-prompt-bar">
<span class="cb-prompt-label">Copy this</span>
<span class="cb-copy">Copy</span></div>
<pre>The text to copy goes here.</pre></div>
```

## 12. Before and After

Use for an old version and a new version of anything.

```html
<div class="cb-ba">
<div class="cb-ba-col cb-before">
<span class="cb-label">Before</span>
<p>The old version.</p>
</div>
<div class="cb-ba-col cb-after">
<span class="cb-label">After</span>
<p>The new version.</p>
</div>
</div>
```

## 13. FAQ

Use for questions and answers. Two to five questions. Answers of two or three sentences.

```html
<div class="cb-faq">
<details>
<summary>The question?</summary>
<p>The answer.</p>
</details>
<details>
<summary>The next question?</summary>
<p>The answer.</p>
</details>
</div>
```

## 14. Image Gallery

Use for three images: one large on the left, two stacked on the right. Clicking an image opens it full size,
and clicking again closes it, with no script. Use square or near-square images for the best fit.
Each gallery needs its own unique lightbox ids.

```html
<div class="cb-gallery">
<a href="#cb-img-1"><img src="IMAGE-1-URL" alt="Describe image one" width="1254" height="1254"></a>
<a href="#cb-img-2"><img src="IMAGE-2-URL" alt="Describe image two" width="1254" height="1254"></a>
<a href="#cb-img-3"><img src="IMAGE-3-URL" alt="Describe image three" width="1254" height="1254"></a>
</div>
<div id="cb-img-1" class="cb-lightbox"><a class="cb-lightbox-close" href="#cb-close">Close</a><img src="IMAGE-1-URL" alt="Describe image one"></div>
<div id="cb-img-2" class="cb-lightbox"><a class="cb-lightbox-close" href="#cb-close">Close</a><img src="IMAGE-2-URL" alt="Describe image two"></div>
<div id="cb-img-3" class="cb-lightbox"><a class="cb-lightbox-close" href="#cb-close">Close</a><img src="IMAGE-3-URL" alt="Describe image three"></div>
```

The owner uploads images in the admin and gives you the URLs. Never invent an image URL.

## 15. Video

Use a landscape video, a portrait Short, or a grid of two or three videos. Use the video id from the YouTube
link (`watch?v=ID` or `shorts/ID`).

Landscape:

```html
<div class="cb-video"><iframe src="https://www.youtube-nocookie.com/embed/VIDEO-ID" title="Describe the video" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen loading="lazy"></iframe></div>
```

Portrait Short (add `cb-short`):

```html
<div class="cb-video cb-short"><iframe src="https://www.youtube-nocookie.com/embed/VIDEO-ID" title="Describe the video" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen loading="lazy"></iframe></div>
```

Video Pair (landscape video with a Short beside it at the same height on large screens, stacked on phones):

```html
<div class="cb-video-pair">
<div class="cb-video"><iframe src="https://www.youtube-nocookie.com/embed/LANDSCAPE-ID" title="Describe the video" allowfullscreen loading="lazy"></iframe></div>
<div class="cb-video cb-short"><iframe src="https://www.youtube-nocookie.com/embed/SHORT-ID" title="Describe the Short" allowfullscreen loading="lazy"></iframe></div>
</div>
```

Grid of landscape videos:

```html
<div class="cb-video-grid">
<div class="cb-video"><iframe src="https://www.youtube-nocookie.com/embed/ID-ONE" title="Video one" allowfullscreen loading="lazy"></iframe></div>
<div class="cb-video"><iframe src="https://www.youtube-nocookie.com/embed/ID-TWO" title="Video two" allowfullscreen loading="lazy"></iframe></div>
</div>
```

## 16. Link Row

Use for a set of pill buttons with small icons. Icon classes: `cb-i-play`, `cb-i-mail`, `cb-i-download`,
`cb-i-arrow`, `cb-i-book`. Use two to five links.

```html
<div class="cb-links">
<a class="cb-link cb-i-play" href="URL">Watch the video</a>
<a class="cb-link cb-i-mail" href="mailto:ADDRESS">Email us</a>
<a class="cb-link cb-i-download" href="URL">Download the guide</a>
<a class="cb-link cb-i-book" href="URL">Read the blog</a>
<a class="cb-link cb-i-arrow" href="URL">Visit the shop</a>
</div>
```

## 17. Featured Articles

Use for three other posts the reader may want next. Use real post URLs from the shop. Never invent a link.

```html
<div class="cb-articles">
<span class="cb-label">Keep reading</span>
<div class="cb-articles-grid">
<div class="cb-card">
<h4><a href="/blog/post-slug/">Post title</a></h4>
<p>One sentence about the post.</p>
<a class="cb-more" href="/blog/post-slug/">Read more &rarr;</a>
</div>
<div class="cb-card">
<h4><a href="/blog/post-slug/">Post title</a></h4>
<p>One sentence about the post.</p>
<a class="cb-more" href="/blog/post-slug/">Read more &rarr;</a>
</div>
<div class="cb-card">
<h4><a href="/blog/post-slug/">Post title</a></h4>
<p>One sentence about the post.</p>
<a class="cb-more" href="/blog/post-slug/">Read more &rarr;</a>
</div>
</div>
</div>
```

## 18. Product Box

Use for one product or offer, with the primary theme shade as the background. One button only.

```html
<div class="cb-cta">
<span class="cb-label">From the shop</span>
<h3>Product or offer heading</h3>
<p>Two or three sentences about what the buyer gets.</p>
<a class="cb-btn" href="/shop/product-slug/">Button text &rarr;</a>
</div>
```

---

## Asking for a block

Owners can paste any of these.

- "Turn the text below into a Comparison Table block."
- "Add a This vs That block comparing [A] and [B]."
- "Take this article and add a Contents List, a Key Takeaways box and a Checklist where they fit."
- "Turn this section into a Numbered Steps block."
- "Put this prompt in a Prompt Box so readers can copy it."
- "Make a Product Box for [product] using the primary theme shade."
- "Go into post [id] with the MCP connector and turn the last section into a Checklist."


---

## Appendix A: the stylesheet (content-blocks.css)

Djangify shops already include this file. On any other site, save it as `content-blocks.css` and link it, or
paste it into the site's own CSS. Change the shades in the `:root` block to match the brand.

```css
/* Djangify Content Blocks: standalone stylesheet
   For any website that can use HTML. Djangify shops already include all of this.

   How to use it on another site:
   1. Add this file to your site (a <link> tag in the page head, or paste it into your own CSS).
   2. Wrap your article or page text in <div class="page-content"> ... </div>.
   3. Optional: change the shades in :root below to match your brand.
   4. Optional: add content-blocks.js on the page to make the Prompt Box Copy button work.
*/

:root {
  --color-primary: #365272;
  --color-primary-contrast: #ffffff;
  --color-secondary: #d6c6b3;
  --color-secondary-contrast: #1a1a1a;
  --color-accent: #b85c3b;
  --color-accent-contrast: #ffffff;
  --color-light: #f8fafc;
  --color-light-contrast: #e2e8f0;
  --color-bg-contrast: #f1f5f9;
  --color-link: #2563eb;
  --color-link-hover: #1d4ed8;
}

.page-content { line-height: 1.7; }
.page-content img { max-width: 100%; height: auto; }
.page-content a { color: var(--color-link); }
.page-content a:hover { color: var(--color-link-hover); }
.page-content h2[id], .page-content h3[id] { scroll-margin-top: 5rem; }

/* ==========================================================================
   CONTENT BLOCKS (cb-*) for blog posts and info pages
   Paste-in HTML components: table, compare, facts, callout, toc, cta.
   Unlayered + scoped to .page-content so they beat preflight and the
   .page-content link rules. Colours come from the Site Settings theme vars.
   ========================================================================== */

/* Plain tables inside CMS content get sane defaults */
.page-content table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 1rem;
}

/* Scroll wrapper so wide tables never break the phone layout */
.page-content .cb-table-wrap {
  overflow-x: auto;
  margin: 1.5rem 0;
  border: 1px solid #e2e8f0;
  border-radius: 0.75rem;
  -webkit-overflow-scrolling: touch;
}

.page-content .cb-table {
  margin: 0;
  min-width: 32rem;
  font-size: 0.95rem;
  line-height: 1.5;
}

.page-content .cb-table caption {
  caption-side: top;
  padding: 0.75rem 1rem;
  text-align: left;
  font-weight: 600;
  background: var(--color-bg-contrast);
}

.page-content .cb-table th,
.page-content .cb-table td {
  padding: 0.75rem 1rem;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid #e2e8f0;
}

.page-content .cb-table thead th {
  background: var(--color-primary);
  color: var(--color-primary-contrast);
  font-weight: 600;
  border-bottom: 0;
}

.page-content .cb-table tbody tr:nth-child(even) {
  background: var(--color-light);
}

.page-content .cb-table tbody tr:last-child td {
  border-bottom: 0;
}

.page-content .cb-table tbody th {
  font-weight: 600;
}

/* This vs that: two side-by-side cards, stacked on phones */
.page-content .cb-compare {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  margin: 1.5rem 0;
}

@media (min-width: 768px) {
  .page-content .cb-compare {
    grid-template-columns: 1fr 1fr;
  }
}

.page-content .cb-compare-col {
  background: var(--color-light);
  border: 1px solid #e2e8f0;
  border-top: 4px solid var(--color-primary);
  border-radius: 0.75rem;
  padding: 1.25rem 1.5rem;
}

.page-content .cb-compare-col.cb-b {
  border-top-color: var(--color-accent);
}

.page-content .cb-compare-col h3,
.page-content .cb-compare-col h4 {
  margin-top: 0;
  margin-bottom: 0.75rem;
}

.page-content .cb-compare-col ul {
  margin-bottom: 0;
}

/* Facts row: big number or word plus a short label */
.page-content .cb-facts {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  margin: 1.5rem 0;
}

@media (min-width: 640px) {
  .page-content .cb-facts {
    grid-template-columns: repeat(3, 1fr);
  }
}

.page-content .cb-fact {
  background: var(--color-light);
  border: 1px solid #e2e8f0;
  border-radius: 0.75rem;
  padding: 1.25rem;
  text-align: center;
}

.page-content .cb-fact strong {
  display: block;
  font-size: 1.75rem;
  line-height: 1.2;
  color: var(--color-primary);
}

.page-content .cb-fact span {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.95rem;
}

/* Callout: key insight or tip */
.page-content .cb-callout {
  background: var(--color-light);
  border-left: 4px solid var(--color-accent);
  border-radius: 0 0.75rem 0.75rem 0;
  padding: 1rem 1.5rem;
  margin: 1.5rem 0;
}

.page-content .cb-callout > :last-child {
  margin-bottom: 0;
}

.page-content .cb-callout .cb-label {
  display: block;
  margin-bottom: 0.25rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-accent);
}

/* Table of contents: links to the post's own headings */
.page-content .cb-toc {
  background: var(--color-light);
  border: 1px solid #e2e8f0;
  border-radius: 0.75rem;
  padding: 1.25rem 1.5rem;
  margin: 1.5rem 0;
}

.page-content .cb-toc .cb-label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.page-content .cb-toc ol {
  margin-bottom: 0;
}

.page-content .cb-toc li:last-child {
  margin-bottom: 0;
}

.page-content h2[id],
.page-content h3[id] {
  scroll-margin-top: 5rem;
}

/* Product panel: dark box with a heading, text and one button */
.page-content .cb-cta {
  background: var(--color-primary);
  color: var(--color-primary-contrast);
  border-radius: 1rem;
  padding: 2rem;
  margin: 2rem 0;
}

.page-content .cb-cta .cb-label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.85;
}

.page-content .cb-cta h2,
.page-content .cb-cta h3 {
  margin-top: 0;
  color: inherit;
}

.page-content .cb-cta > :last-child {
  margin-bottom: 0;
}

.page-content .cb-cta a.cb-btn {
  display: inline-block;
  margin-top: 0.5rem;
  padding: 0.75rem 1.5rem;
  border-radius: 0.375rem;
  background: #000000;
  color: #ffffff;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.page-content .cb-cta a.cb-btn:hover {
  background: var(--color-secondary);
  color: var(--color-secondary-contrast);
  text-decoration: none;
}

/* ---- Content blocks, part 2 ---- */

/* Quote */
.page-content .cb-quote {
  background: var(--color-light);
  border-left: 4px solid var(--color-primary);
  border-radius: 0 0.75rem 0.75rem 0;
  padding: 1.25rem 1.5rem;
  margin: 1.5rem 0;
  font-size: 1.1rem;
  font-style: italic;
}
.page-content .cb-quote p:last-child { margin-bottom: 0; }
.page-content .cb-quote .cb-source {
  margin-top: 0.75rem;
  font-size: 0.9rem;
  font-style: normal;
  font-weight: 600;
}

/* Two Lists */
.page-content .cb-lists {
  background: var(--color-light);
  border: 1px solid #e2e8f0;
  border-radius: 1rem;
  padding: 1.5rem;
  margin: 1.5rem 0;
}
.page-content .cb-lists > h3 { margin-top: 0; }
.page-content .cb-lists-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}
@media (min-width: 768px) {
  .page-content .cb-lists-grid { grid-template-columns: 1fr 1fr; }
}
.page-content .cb-list-box {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-top: 4px solid var(--color-primary);
  border-radius: 0.75rem;
  padding: 1rem 1.25rem;
}
.page-content .cb-list-box.cb-b { border-top-color: var(--color-accent); }
.page-content .cb-list-box h4 { margin-top: 0; margin-bottom: 0.5rem; }
.page-content .cb-list-box ul { margin-bottom: 0; }

/* Numbered Steps */
.page-content ol.cb-steps {
  list-style: none;
  padding-left: 0;
  margin: 1.5rem 0;
  counter-reset: cbstep;
}
.page-content ol.cb-steps > li {
  counter-increment: cbstep;
  position: relative;
  margin: 0;
  padding: 0 0 1.5rem 3.5rem;
  min-height: 2.5rem;
}
.page-content ol.cb-steps > li::before {
  content: counter(cbstep);
  position: absolute;
  left: 0;
  top: 0;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 9999px;
  background: var(--color-primary);
  color: var(--color-primary-contrast);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.page-content ol.cb-steps > li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 1.05rem;
  top: 2.6rem;
  bottom: 0.25rem;
  width: 2px;
  background: #e2e8f0;
}
.page-content ol.cb-steps > li strong { display: block; font-size: 1.1rem; }
.page-content ol.cb-steps > li span { display: block; }

/* Checklist (primary background) */
.page-content .cb-checklist {
  background: var(--color-primary);
  color: var(--color-primary-contrast);
  border-radius: 1rem;
  padding: 2rem;
  margin: 2rem 0;
}
.page-content .cb-checklist .cb-label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.85;
}
.page-content .cb-checklist h3 { margin-top: 0; color: inherit; }
.page-content .cb-checklist ul {
  list-style: none;
  padding-left: 0;
  margin: 1rem 0 0;
}
.page-content .cb-checklist li {
  position: relative;
  margin: 0;
  padding: 0.9rem 0 0.9rem 2.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.25);
}
.page-content .cb-checklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.1rem;
  width: 1.4rem;
  height: 1.4rem;
  border: 2px solid currentColor;
  border-radius: 0.35rem;
}
.page-content .cb-checklist li strong { display: block; }
.page-content .cb-checklist li span { display: block; opacity: 0.85; font-size: 0.95rem; }
.page-content .cb-checklist > :last-child { margin-bottom: 0; }

/* Prompt / Code box */
.page-content .cb-prompt {
  border: 1px solid #e2e8f0;
  border-radius: 0.75rem;
  overflow: hidden;
  margin: 1.5rem 0;
  background: #ffffff;
}
.page-content .cb-prompt-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6rem 1rem;
  background: var(--color-light);
  border-bottom: 1px solid #e2e8f0;
}
.page-content .cb-prompt-label {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.page-content .cb-copy {
  display: inline-block;
  padding: 0.3rem 0.9rem;
  border: 1px solid #cbd5e1;
  border-radius: 0.375rem;
  background: #ffffff;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  user-select: none;
}
.page-content .cb-copy:hover { background: var(--color-light-contrast); }
.page-content .cb-prompt pre {
  margin: 0;
  padding: 1rem;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 0.9rem;
  line-height: 1.6;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* FAQ */
.page-content .cb-faq { margin: 1.5rem 0; }
.page-content .cb-faq details {
  border: 1px solid #e2e8f0;
  border-radius: 0.75rem;
  background: #ffffff;
  margin-bottom: 0.75rem;
  padding: 0 1.25rem;
}
.page-content .cb-faq summary {
  cursor: pointer;
  padding: 1rem 0;
  font-weight: 600;
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: 1rem;
}
.page-content .cb-faq summary::-webkit-details-marker { display: none; }
.page-content .cb-faq summary::after {
  content: "+";
  font-size: 1.4rem;
  line-height: 1;
  color: var(--color-primary);
}
.page-content .cb-faq details[open] summary::after { content: "\2212"; }
.page-content .cb-faq details > :last-child { margin-bottom: 1rem; }

/* Key Takeaways */
.page-content .cb-takeaways {
  background: var(--color-light);
  border: 1px solid #e2e8f0;
  border-top: 4px solid var(--color-primary);
  border-radius: 0.75rem;
  padding: 1.25rem 1.5rem;
  margin: 1.5rem 0;
}
.page-content .cb-takeaways .cb-label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-primary);
}
.page-content .cb-takeaways ul { margin-bottom: 0; }

/* Before and After */
.page-content .cb-ba {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  margin: 1.5rem 0;
}
@media (min-width: 768px) {
  .page-content .cb-ba { grid-template-columns: 1fr 1fr; }
}
.page-content .cb-ba-col {
  border-radius: 0.75rem;
  padding: 1.25rem 1.5rem;
  border: 1px solid #e2e8f0;
}
.page-content .cb-ba-col.cb-before { background: #f8fafc; border-style: dashed; }
.page-content .cb-ba-col.cb-after { background: #ffffff; border: 2px solid var(--color-primary); }
.page-content .cb-ba-col .cb-label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.page-content .cb-ba-col > :last-child { margin-bottom: 0; }

/* Featured Articles */
.page-content .cb-articles { margin: 2rem 0; }
.page-content .cb-articles > .cb-label {
  display: block;
  margin-bottom: 0.75rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.page-content .cb-articles-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}
@media (min-width: 768px) {
  .page-content .cb-articles-grid { grid-template-columns: repeat(3, 1fr); }
}
.page-content .cb-card {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 0.75rem;
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
}
.page-content .cb-card:hover { border-color: var(--color-primary); }
.page-content .cb-card h4 { margin-top: 0; margin-bottom: 0.5rem; font-size: 1.05rem; line-height: 1.35; }
.page-content .cb-card p { font-size: 0.95rem; flex-grow: 1; }
.page-content .cb-card .cb-more { font-weight: 600; text-decoration: none; }

/* Image Gallery: one large left, two stacked right, click to enlarge (no script) */
.page-content .cb-gallery {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 0.5rem;
  margin: 1.5rem 0;
}
.page-content .cb-gallery a {
  display: block;
  overflow: hidden;
  border-radius: 0.75rem;
  text-decoration: none;
  cursor: zoom-in;
}
.page-content .cb-gallery a:first-child { grid-row: 1 / span 2; }
.page-content .cb-gallery img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.page-content .cb-lightbox {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0, 0, 0, 0.88);
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.page-content .cb-lightbox:target { display: flex; }
.page-content .cb-lightbox img {
  position: relative;
  z-index: 1;
  pointer-events: none;
  max-width: 100%;
  max-height: 92vh;
  object-fit: contain;
}
.page-content a.cb-lightbox-close {
  position: absolute;
  inset: 0;
  padding: 1rem 1.5rem;
  text-align: right;
  color: #ffffff;
  font-weight: 600;
  text-decoration: none;
  cursor: zoom-out;
}
.page-content a.cb-lightbox-close:hover { color: #ffffff; text-decoration: none; }

/* Video */
.page-content .cb-video {
  position: relative;
  aspect-ratio: 16 / 9;
  margin: 1.5rem 0;
  border-radius: 0.75rem;
  overflow: hidden;
  background: #000000;
}
.page-content .cb-video.cb-short {
  aspect-ratio: 9 / 16;
  max-width: 22rem;
  margin-left: auto;
  margin-right: auto;
}
.page-content .cb-video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.page-content .cb-video-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1rem;
  margin: 1.5rem 0;
}
.page-content .cb-video-grid .cb-video { margin: 0; }

/* Link Row: pill buttons with a small icon */
.page-content .cb-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 1.5rem 0;
}
.page-content a.cb-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.65rem 1.15rem;
  border-radius: 0.375rem;
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.page-content a.cb-link:hover {
  background: var(--color-secondary);
  color: var(--color-secondary-contrast);
  text-decoration: none;
}
.page-content a.cb-link::before {
  content: "";
  width: 1.1rem;
  height: 1.1rem;
  background-color: currentColor;
  -webkit-mask: var(--cb-icon, none) center / contain no-repeat;
  mask: var(--cb-icon, none) center / contain no-repeat;
}
.page-content a.cb-i-play { --cb-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M8 5v14l11-7z'/%3E%3C/svg%3E"); }
.page-content a.cb-i-mail { --cb-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='2'/%3E%3Cpath d='M3 7l9 6 9-6'/%3E%3C/svg%3E"); }
.page-content a.cb-i-download { --cb-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4v11M7 11l5 5 5-5M5 20h14'/%3E%3C/svg%3E"); }
.page-content a.cb-i-arrow { --cb-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17L17 7M9 7h8v8'/%3E%3C/svg%3E"); }
.page-content a.cb-i-book { --cb-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 4h14v16H5zM9 4v16'/%3E%3C/svg%3E"); }

/* Product Box: optional image inside the text */
.page-content .cb-cta img { border-radius: 0.5rem; max-width: 100%; height: auto; }

/* Video pair: landscape and portrait side by side on large screens, stacked on small ones */
.page-content .cb-video-pair {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  margin: 1.5rem 0;
}
.page-content .cb-video-pair .cb-video { margin: 0; }
@media (min-width: 768px) {
  .page-content .cb-video-pair {
    grid-template-columns: 3fr 1fr;
    align-items: stretch;
  }
  .page-content .cb-video-pair .cb-video.cb-short {
    aspect-ratio: auto;
    max-width: none;
    height: 100%;
    min-height: 0;
  }
}


/* Guards for sites that use the Tailwind typography plugin (.prose) */
.page-content .cb-prompt pre {
  background: transparent;
  color: inherit;
  border-radius: 0;
}
.page-content .cb-checklist strong,
.page-content .cb-cta strong,
.page-content .cb-cta h3,
.page-content .cb-checklist h3 { color: inherit; }
.page-content .cb-quote { quotes: none; }
.page-content .cb-quote p::before,
.page-content .cb-quote p::after { content: none; }
.page-content .cb-gallery img,
.page-content .cb-lightbox img { margin: 0; }
.page-content .cb-table-wrap table,
.page-content .cb-table { margin: 0; }
.page-content .cb-faq details > p { margin-top: 0; }
.page-content .cb-checklist ul,
.page-content .cb-checklist li { color: inherit; }
/* Some sites set list-style with !important in the base layer; match that layer so the blocks win. */
@layer base {
  .page-content ol.cb-steps,
  .page-content .cb-checklist ul { list-style: none !important; }
}
```

## Appendix B: the Copy button script (content-blocks.js)

Optional. Save it as `content-blocks.js` and add it to the page with `<script src="content-blocks.js" defer></script>`.

```javascript
// Copy button for the "Prompt Box" content block (.cb-prompt).
// The text lives in the <pre>, so it stays readable without this script.
document.addEventListener("click", function (e) {
  var btn = e.target.closest(".cb-copy");
  if (!btn) return;
  var box = btn.closest(".cb-prompt");
  var pre = box && box.querySelector("pre");
  if (!pre) return;

  var done = function () {
    var old = btn.getAttribute("data-label") || btn.textContent;
    btn.setAttribute("data-label", old);
    btn.textContent = "Copied";
    setTimeout(function () { btn.textContent = old; }, 1800);
  };

  // Older route: select the text and use the browser's copy command.
  var fallback = function () {
    var range = document.createRange();
    range.selectNodeContents(pre);
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
    var ok = false;
    try { ok = document.execCommand("copy"); } catch (err) {}
    if (ok) {
      done();
      sel.removeAllRanges();
    }
    // If copying is blocked, the text stays selected so the reader can press Ctrl+C.
  };

  if (navigator.clipboard && navigator.clipboard.writeText) {
    navigator.clipboard.writeText(pre.innerText).then(done, fallback);
  } else {
    fallback();
  }
});
```
