/*
 * pm-v2-layout — shared shell width, gutters, content-area constraints.
 *
 * One shared max width: 1200px. Gutters: 16px mobile, 24px desktop.
 */

.pm-v2 .pm-shell {
	width: 100%;
	max-width: var(--pm-max);
	margin-inline: auto;
	padding-inline: var(--pm-gutter);
}

/*
 * The two-column body is GeneratePress' now.
 *
 * The right rail used to live in a `.pm-body` / `.pm-body--with-rail` grid INSIDE the
 * content area. It is `sidebar-1`'s default content now (inc/sidebar.php), so the
 * column is the parent's own flex layout: `.site-content` is `display:flex` and, with
 * the `right-sidebar` layout this theme now resolves on rail surfaces, GP emits
 * `.site-content .content-area { width: 70% }` beside `.is-right-sidebar { width: 30% }`.
 * The child therefore ships NO grid of its own for this column — a second grid inside
 * the content area would fight the parent's flex row and the rail would be pushed
 * under the article.
 *
 * The rail's own fit inside `.inside-right-sidebar` (and the styling of a USER widget
 * placed in that area) lives in rail.css, next to the rail it is fitting.
 */

/* The added posts-index heading follows both palettes; GP owns its spacing. */
.pm-v2 [data-pm-posts-index-title] {
	background-color: var(--surface);
	color: var(--text-strong);
}

.pm-v2 .site-main {
	min-width: 0;
}

.pm-v2 .entry-content > * {
	max-width: 100%;
}

.pm-v2 .entry-content img,
.pm-v2 .entry-content iframe {
	max-width: 100%;
	height: auto;
}

/* Let article screenshots keep their aspect ratio and readable column width.
 * Tall collages scroll with the article instead of shrinking to viewport height.
 * Small images keep their natural width instead of stretching to the column. */
.pm-v2 .entry-content img {
	width: auto;
	object-fit: contain;
}

/* Keep small inline graphics aligned with the surrounding text. */
.pm-v2 .entry-content img[width="16"],
.pm-v2 .entry-content img[width="20"],
.pm-v2 .entry-content img[width="24"],
.pm-v2 .entry-content img[width="32"],
.pm-v2 .entry-content img[width="48"],
.pm-v2 .entry-content img[width="64"],
.pm-v2 .entry-content img[height="15"],
.pm-v2 .entry-content img[height="16"],
.pm-v2 .entry-content img[height="20"] {
	max-height: none;
	width: auto;
	object-fit: fill;
	vertical-align: middle;
}

/*
 * Wide tables in long legacy posts must scroll rather than blow out the grid.
 * The table is wrapped in a scroll container instead of being displayed as a
 * block so its own internal layout (widths, colgroup, alignment) is preserved.
 */
.pm-v2 .entry-content table {
	display: table;
	max-width: 100%;
	border-collapse: collapse;
}

/*
 * A DIRECT-child table could scroll, but a table NESTED inside a wrapper div could not:
 * the rule only matched `.entry-content > table`, so a legacy post that wraps its table in
 * a container (very common — an editor block or pasted markup emits
 * `<div class="table__wrapper"><table>…`) still overflowed. Measured at 360px on
 * post 25079: the page scrolled 6px sideways because a 305px table sat in a 345px column
 * with no scroll container of its own.
 *
 * The wrapper — not the table — is made the scroller. Making the TABLE itself
 * `display: block; overflow-x: auto` would collapse its internal table layout, so the
 * scroll is applied to the nearest block ancestor instead, which keeps the table's own
 * widths intact while containing the overflow.
 */
.pm-v2 .entry-content > table,
.pm-v2 .entry-content :where(div, figure, p) > table {
	display: block;
	overflow-x: auto;
	max-width: 100%;
	/* A hair of bottom room so a scrollbar cannot clip the last row. */
	-webkit-overflow-scrolling: touch;
}

/* The wrapper the legacy markup puts around a table is itself the scroll container when
   present; this catches the case where the table is not the element that overflows. */
.pm-v2 .entry-content .table__wrapper,
.pm-v2 .entry-content [class*="table__wrapper"] {
	max-width: 100%;
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

.pm-v2 .entry-content th,
.pm-v2 .entry-content td {
	border: 1px solid var(--border);
	padding: var(--sp-2) var(--sp-3);
}

.pm-v2 .entry-content th {
	background-color: var(--surface);
	text-align: left;
}

/*
 * The download-plugin's inline `display-name` span can be wider than the column on a
 * narrow screen. It is given permission to wrap instead of forcing the row wider than
 * the viewport.
 */
.pm-v2 .entry-content .display-name {
	overflow-wrap: anywhere;
}

/* ======================================================================== */
/*
 * ARTICLE PROSE TYPOGRAPHY — LIVES HERE ON PURPOSE, NOT IN detail.css.
 *
 * These rules were first written into assets/css/detail.css and appeared to do
 * nothing on a blog post. The cause was not the CSS: detail.css is enqueued only
 * for the SOFTWARE detail surface, so an ordinary post never received it. Measured
 * on post 8076: the sheet list is 8 files (base, controls, footer, header,
 * interactions, layout, rail, tokens) with no detail.css, while a software detail
 * loads 10 and includes it. Blockquote kept its GeneratePress border-left and the
 * heading sizes never applied.
 *
 * layout.css is in BOTH lists, which is why the block belongs here: `h3` appears in
 * 798 of 1497 published posts and most of those are ordinary posts, not software
 * entries. A rule for the blog body must load on the blog body.
 */
/* ==================================================== article prose typography == */

/*
 * The elements below are printed by post content (classic editor markup, pasted
 * legacy tutorials) rather than by a theme component, and had NO rule anywhere in
 * assets/css — they fell back to the browser's own defaults and therefore sat
 * outside the design system entirely. The frequency is not marginal: `h3` appears in
 * 798 of 1497 published posts (53%), `code` in 63, `blockquote` in 15, `pre` in 10
 * and `figure` in 4.
 *
 * Every rule is keyed on `.entry-content`, the class shared by the software detail
 * body (`#pm-content.entry-content`) and the ordinary blog post body, so both
 * surfaces read the same. Nothing here is a blanket `.pm-v2 <tag>` selector.
 *
 * `h2` is deliberately absent: it already has a size on the base layer. `table` is
 * absent too — it is handled in layout.css.
 */
/*
 * `h4` steps down to body size so it reads as a sub-heading of the `h3` above it.
 * Size and spacing ONLY — the weight is the same inherited one the base layer gives
 * the other headings, and it is not set here on purpose: the heading weight is a
 * design decision for the site owner, not a side effect of adding spacing.
 */
/*
 * Blockquote: a tinted surface, inner padding and italic copy. It is marked out by
 * BACKGROUND, not by a coloured bar on the left edge — the left accent bar is the
 * device the download panel and the related block use for their own headings, and
 * borrowing it here would read as another one of those panels rather than as a
 * quotation. `--surface` is the existing quiet grey; no new colour is introduced.
 */
.pm-v2 .entry-content blockquote {
	margin: var(--sp-5) 0;
	padding: var(--sp-4);
	background-color: var(--surface);
	border-radius: var(--r-md);
	font-style: italic;
	color: var(--text);
	/*
	 * `border-left: 0` is UNDOING a parent rule, not decorating. GeneratePress ships
	 * `blockquote { border-left: 5px solid rgba(0,0,0,.05); font-size: 1.2em }` in
	 * `main.min.css`; this theme only wins where it says so explicitly. Left alone, the
	 * parent's grey rail sits under our surface tint and the two treatments fight on the
	 * same block — measured live as `borderLeft: 5px` on a block that declares none.
	 *
	 * A rail is also a pattern the owner has already rejected once (the list-row hover
	 * accent), so a quoted block wearing one would be the same rejected device in a new
	 * place. The quotation is marked by its surface, its inset padding, its italics and
	 * its attribution line — four cues, none of them a bar.
	 *
	 * `font-size` is pinned for the same reason: the parent's `1.2em` would otherwise
	 * scale with whatever size the block inherits, so a quote nested in a list would be
	 * larger than one at the top level.
	 */
	border-left: 0;
	font-size: var(--fs-body);
}

/* The last child keeps no bottom margin, so the surface's padding — not a collapsing
   margin — fixes the gap to whatever follows the quotation. */
.pm-v2 .entry-content blockquote > :last-child {
	margin-bottom: 0;
}

.pm-v2 .entry-content blockquote cite {
	display: block;
	margin-top: var(--sp-2);
	font-size: var(--fs-meta);
	font-style: normal;
	color: var(--muted);
}

/*
 * Inline `code` is a text-level mark inside a sentence: font swap plus a flat tint
 * and nothing else. It must stay inline — no padding box large enough to disturb the
 * line height, no border. The monospace family itself comes from base.css.
 */
.pm-v2 .entry-content code {
	padding: 0.1em 0.35em;
	background-color: var(--surface);
	border-radius: var(--r-sm);
}

/*
 * `pre` is the block-level sibling and has to be unmistakably different from the
 * inline mark above: it keeps its own padding box, sets the mono family again at a
 * legible size, and scrolls sideways instead of wrapping. `overflow-x: auto` is
 * load-bearing — terminal output and code samples are whitespace-significant, and
 * wrapping one silently reflows it into something that no longer matches what the
 * tutorial shows. The block scrolls; the page never does.
 */
.pm-v2 .entry-content pre {
	margin: var(--sp-5) 0;
	padding: var(--sp-3) var(--sp-4);
	background-color: var(--surface);
	border: 1px solid var(--border);
	border-radius: var(--r-md);
	overflow-x: auto;
	font-family: var(--pm-font-mono);
	font-size: var(--fs-meta);
	line-height: 1.6;
	-webkit-overflow-scrolling: touch;
}

/* `pre` is the pager here, so an inner `<code>` must not repaint the tint or add an
   inset box inside it. */
.pm-v2 .entry-content pre code {
	padding: 0;
	background-color: transparent;
	border-radius: 0;
}

/* ------------------------------------------------------------------- figures -- */

/* WordPress emits `figure` for a captioned image and for the `wp-block-image`
   block. It carries a default UA margin that ignores the spacing scale, so the
   rhythm here has to be declared. */
.pm-v2 .entry-content figure {
	margin: var(--sp-5) 0;
}

/* The caption is metadata about the picture, not prose: smaller, quieter than the
   body and centred under its figure. */
.pm-v2 .entry-content figcaption {
	margin-top: var(--sp-2);
	font-size: var(--fs-meta);
	color: var(--muted);
	text-align: center;
}

/* Primary GP navigation stays in flow on every surface, never the slideout. */
.pm-v2 #site-navigation:not(.slideout-navigation),
.pm-v2 #mobile-header:not(.slideout-navigation) {
	position: sticky;
	top: var(--pm-admin-occlusion, var(--wp-admin--admin-bar--height, 0px));
	z-index: 500;
}

/* One anchor contract: the cluster lives in scroll-padding, not target margins.
   CSS estimates cover the interval before the deferred measurement runs. */
html:has(body.pm-v2) {
	--pm-secondary-height: 0px;
	scroll-padding-top: var(--pm-sticky-cluster, calc(var(--wp-admin--admin-bar--height, 0px) + 64px + var(--pm-secondary-height)));
}

html:has(body.pm-v2 [data-pm-section-nav]) {
	--pm-secondary-height: 48px;
}

/* No JS leaves the native menu expanded: its height is unbounded, so neither
   navigation pins over the article. Higher specificity also beats detail.css. */
html:not(.pm-has-js) .pm-v2 #site-navigation:not(.slideout-navigation),
html:not(.pm-has-js) .pm-v2 #mobile-header:not(.slideout-navigation),
html:not(.pm-has-js) .pm-v2 .pm-detail__nav {
	position: relative;
	top: auto;
	z-index: auto;
}

html:not(.pm-has-js):has(body.pm-v2) {
	scroll-padding-top: calc(var(--wp-admin--admin-bar--height, 0px) + 8px);
}
