/* ARTICLE BODY + TABLE OF CONTENTS — .db-article  (blog-post = 1)
   Body copy with a sticky sidebar TOC: stacked above the text on mobile,
   a right-hand column from 861px.

   The TOC is generated by assets/js/toc.js from the h2s in the body — it is
   NOT authored. Hand-maintaining a contents list against editable prose is
   exactly the kind of thing that silently rots, and the prototype's version
   was a hardcoded PHP array that had to be kept in sync by hand.

   ⚠️ THE BODY'S VERTICAL RHYTHM IS THREE GAPS, NOT ONE (§9.54). The frame nests
   the prose — section ▸ heading+intro ▸ h3+list — and each level has its own
   gap, but post_content is a flat list of blocks. So one flex gap carries the
   middle distance and the headings correct outwards from it:

                       mobile   desktop
       section ▸ section   40        60     h2 margin-top   (+20 / +36)
       h3 ▸ list / bullets 20        24     the flex gap
       h2 ▸ intro           8        12     h2 margin-bottom (-12)
       h3 ▸ list            8        12     h3 margin-bottom (-12)

   Frames: 368:2558 (desktop), 368:5092 (mobile). */
.db-article { display: flex; flex-direction: column; gap: 32px; padding-block: 20px 40px; }

.db-article__toc { order: -1; }
.db-article__toc-inner { display: flex; flex-direction: column; gap: 24px; }
/* ⚠️ Doubled up on purpose. Since §9.66 the post-content wrapper itself carries
   `db-article__body`, which makes the TOC a *descendant* of it rather than a
   sibling — so `.db-article__body p` (0,1,1) would repaint this heading as body
   copy. It is a `<p>` for outline reasons, not because it is prose. */
.db-article__toc .db-article__toc-title {
	font-family: var(--font-display); font-size: 14px; line-height: 20px;
	text-transform: uppercase; color: var(--ink);
}
.db-article__toc ol { display: flex; flex-direction: column; gap: 12px; margin: 0; padding: 0; list-style: none; }
.db-article__toc li a {
	font-family: var(--font-body); font-weight: 300; font-size: 14px; line-height: 20px;
	color: rgba(37, 32, 30, 0.6); transition: color .2s ease;
}
.db-article__toc li.is-active a,
.db-article__toc li a:hover { color: var(--ink); }
/* Divider only in stacked mode — suppressed once it becomes a sidebar. */
.db-article__toc::after { content: ""; display: block; margin-top: 32px; height: 1px; background: var(--line); }

/* Empty until toc.js fills it, so it never shows a bare heading. */
.db-article__toc:not(.is-ready) { display: none; }

.db-article__body { display: flex; flex-direction: column; gap: 20px; min-width: 0; }

/* ⚠️ A post the client simply types has no `db-article` row: no TOC, nothing to
   sit beside, and so nothing that produced the 920 measure — the prose ran the
   full 1360 and the h2s came out at theme.json's 80px (§9.66). `single.html`
   now puts `db-article__body` on post-content itself, which supplies the
   typography; this supplies the column, but ONLY when the row is absent, so a
   post built the other way is untouched. Matched through `db-post__inner` so it
   can never catch the inner body of a post that does have the row. */
.db-post__inner > .db-article__body:not(:has(.db-article)) { max-width: 920px; padding-block: 20px 40px; }

/* The editor canvas has no template around the content, so none of the above
   reaches it — same problem and same shape of fix as §9.64's job body. The
   canvas body carries `post-type-post`; `:has()` keeps the row-based posts,
   which are already correct there, out of it. */
body.post-type-post .is-root-container:not(:has(> .db-article)) {
	display: flex; flex-direction: column; gap: 20px;
	max-width: calc(920px + var(--wp--style--root--padding-left) + var(--wp--style--root--padding-right));
	margin-left: max(0px, calc((100% - var(--wp--style--root--padding-left) - var(--wp--style--root--padding-right) - var(--wp--style--global--content-size, 1360px)) / 2));
}
/* Trap 28 — core centres and shrink-wraps flex children of the root container
   with `margin-left: auto !important`; a definite width leaves it nothing to take. */
body.post-type-post .is-root-container:not(:has(> .db-article)) > * { width: 100%; }

.db-article__lead { font-size: 16px; line-height: 28px; color: var(--muted); }

.db-article__body h2,
body.post-type-post .is-root-container h2 {
	margin-top: 20px;        /* 20 + the 20px gap = the 40px between sections */
	margin-bottom: -12px;    /* 20 − 12 = the 8px down to the intro paragraph */
	font-size: 1.125rem; line-height: 28px; color: var(--ink);
	scroll-margin-top: 120px;   /* clear the fixed header when jumping from the TOC */
}
.db-article__body > *:first-child,
body.post-type-post .is-root-container > *:first-child { margin-top: 0; }

.db-article__body h3,
body.post-type-post .is-root-container h3 {
	margin-bottom: -12px;
	font-family: var(--font-display); font-size: 14px; line-height: 20px;
	text-transform: uppercase; color: var(--ink);
}

.db-article__body p,
body.post-type-post .is-root-container p { font-size: 16px; line-height: 28px; color: var(--muted); }

/* The line that closes each section — "Fazit: …" — is set in medium. */
.db-article__note { font-weight: 500; }

.db-article__body ul,
body.post-type-post .is-root-container ul { display: flex; flex-direction: column; gap: 2px; padding-left: 0; list-style: none; }
.db-article__body ul li,
body.post-type-post .is-root-container ul li { position: relative; padding-left: 14px; font-size: 16px; line-height: 28px; color: var(--muted); }
.db-article__body ul li::before,
body.post-type-post .is-root-container ul li::before {
	content: ""; position: absolute; left: 0; top: 12px;
	width: 6px; height: 6px; border-radius: 50%; background: var(--gold);
}

.db-article__body figure,
body.post-type-post .is-root-container figure { margin: 0; }
.db-article__body img,
body.post-type-post .is-root-container img { width: 100%; height: 300px; object-fit: cover; }

/* Two images side by side keep the row on mobile, at half the height.
   ⚠️ Two separate cascade traps here, both from core rather than from us:
   the gallery's gap comes from a custom property set by a per-instance rule
   (`.wp-block-gallery-N`) printed inline in the body — same specificity as a
   plain class of ours but later in the document, so it wins; and the images are
   sized by an `is-cropped` rule whose `:not(#individual-image)` gives it ID
   specificity, so no class selector can outrank the `height: 100%` it puts on
   the img. The height therefore goes on the figure, and core's own 100% fills
   it — which is why these selectors are longer than they look like they need
   to be, and why the img is left alone. */
.db-article__body .db-article__pair.has-nested-images { --wp--style--unstable-gallery-gap: 10px; gap: 10px; }
.db-article__body .db-article__pair.has-nested-images figure.wp-block-image { height: 160px; }

@media (min-width: 861px) {
	.db-article { flex-direction: row; align-items: flex-start; gap: 60px; padding-block: 0 120px; }
	/* 1360 content − 920 body − 60 gap = 380 */
	.db-article__toc { order: 2; flex: 0 0 clamp(260px, 28%, 380px); min-width: 0; align-self: stretch; }
	/* ⚠️ Editor canvas, and the same 380 by the same arithmetic — see §9.65.
	   The TOC is a `core/html` block, and the editor wraps every block in its
	   own `div.wp-block-html`. That wrapper, not the `<aside>`, is the flex
	   child here, so the rule above lands one level too deep and the wrapper
	   took part in the row as a shrink-to-fit box: the body started ~200-360px
	   in from the title and ran 1095 wide instead of 920, wrapping nowhere near
	   where the visitor's does. `.wp-block-html` exists only in the editor, so
	   this can never reach the front of the site. Group blocks do NOT have this
	   problem — core copies a group's `className` onto its wrapper, which is
	   why `.db-article__body` beside it was always right. */
	.db-article > .wp-block-html { order: 2; flex: 0 0 clamp(260px, 28%, 380px); min-width: 0; }
	.db-article__toc::after { display: none; }
	.db-article__toc-inner { position: sticky; top: 120px; }

	.db-article__body { flex: 1 1 auto; gap: 24px; }
	/* Plain post — the column's own padding, matching `.db-article` above. */
	.db-post__inner > .db-article__body:not(:has(.db-article)) { padding-block: 0 120px; }
	body.post-type-post .is-root-container:not(:has(> .db-article)) { gap: 24px; }
	.db-article__body h2,
	body.post-type-post .is-root-container h2 { margin-top: 36px; font-size: 1.5rem; line-height: 32px; }
	.db-article__body h3,
	body.post-type-post .is-root-container h3 { font-size: 16px; line-height: 24px; }
	.db-article__body ul,
	body.post-type-post .is-root-container ul { gap: 6px; }
	.db-article__body img,
	body.post-type-post .is-root-container img { height: 420px; }
	.db-article__body .db-article__pair.has-nested-images { --wp--style--unstable-gallery-gap: 16px; gap: 16px; }
	.db-article__body .db-article__pair.has-nested-images figure.wp-block-image { height: 420px; }
}
