/*
 * ARTICLE surface styles — single posts and the post archives.
 *
 * WHAT THIS FILE IS FOR
 * ---------------------
 * `content.css` (another workstream) styles the shared `.nv-main` / `.nv-prose` /
 * `.nv-article*` / `.nv-card*` classes that `page.html`, `search.html` and these templates all
 * use. This file does NOT restate those rules; it refines them for the editorial surface only,
 * behind two scope classes that appear on nothing else:
 *
 *   .nv-editorial       on <main> in single.html
 *   .nv-editorial-list  on <main> in archive.html
 *
 * `inc/article.php` enqueues it at priority 30, after content.css at 20, so where the two
 * touch the same declaration source order decides — deliberately, not by accident.
 *
 * Rules this file follows (DESIGN.md):
 *   - tokens only; a literal colour, font size or spacing value here is a bug
 *   - container queries, never viewport breakpoints
 *   - 44px minimum touch targets, visible focus, real semantics
 *
 * THE ONE MEASUREMENT THAT DROVE MOST OF THIS
 * -------------------------------------------
 * Every lead image on a text post in this database is 1140x317 — a 3.6:1 banner strip, not a
 * photograph. The template that shipped before this pass cropped them into a 4:3 card thumb,
 * which threw away roughly two thirds of every one of them. Client references are 500x500
 * LOGOS and photo-set covers are 900x900. Three different shapes, so three treatments, chosen
 * from what the assets actually are rather than from one grid that suits none of them.
 */

/* ---------------------------------------------------------------------------
 * 1. THE ARTICLE HEAD
 *
 * Eyebrow, then title, then meta. The eyebrow is the section name, and it is the page's only
 * visible breadcrumb — AIOSEO already emits a BreadcrumbList in JSON-LD, so the machine trail
 * exists and the human one only has to answer "where am I", which one word does.
 * ------------------------------------------------------------------------ */

.nv-editorial .nv-editorial__head {
	margin-block-end: var(--wp--preset--spacing--md);
}

.nv-eyebrow {
	margin: 0 0 var(--wp--preset--spacing--xxs);
	font-size: var(--wp--preset--font-size--xs);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	line-height: 1.2;
}

.nv-eyebrow__link {
	display: inline-flex;
	align-items: center;
	/* 44px touch target without a 44px-tall label: the box is padded, the text is not. */
	min-block-size: 44px;
	color: var(--wp--preset--color--brand);
	text-decoration: none;
}

.nv-eyebrow__link:hover,
.nv-eyebrow__link:focus-visible {
	text-decoration: underline;
}

/*
 * The title is the loudest thing on the page and it earns that: these are questions a buyer
 * typed into a search engine. content.css caps it at 20ch, which on a 62-character headline
 * like "Как установить сферическое дорожное зеркало. Требования к установке уличных зеркал"
 * forces four ragged lines. 24ch in Roboto Condensed is still a strong stack without the rag.
 */
.nv-editorial .nv-article__title {
	max-inline-size: 24ch;
	margin-block-end: var(--wp--preset--spacing--xxs);
	line-height: 1.1;
	letter-spacing: -0.01em;
}

/* ---------------------------------------------------------------------------
 * 2. METADATA
 *
 * One quiet line, separated by a middot rather than by pipes or borders. What is IN it is
 * decided in PHP and argued in inc/article.php; this only has to make it recede.
 * ------------------------------------------------------------------------ */

.nv-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--wp--preset--spacing--xxs);
	margin: 0;
	color: var(--wp--preset--color--text-muted);
	font-size: var(--wp--preset--font-size--sm);
	line-height: 1.4;
}

/*
 * The separator is generated, so it is never read out by a screen reader and never selected
 * when a reader copies the line. `+` means it appears only BETWEEN items, so a post with one
 * meta item does not get a leading dot.
 */
.nv-meta__item + .nv-meta__item::before {
	content: "·";
	margin-inline-end: var(--wp--preset--spacing--xxs);
	color: var(--wp--preset--color--border);
}

/* ---------------------------------------------------------------------------
 * 3. THE LEAD IMAGE
 *
 * Three shapes, three treatments, keyed on the `nv-shape-*` body class inc/article.php emits.
 * ------------------------------------------------------------------------ */

/*
 * Guides and news: a 1140x317 banner. Run it the full width of the article column at its own
 * ratio and impose nothing — content.css caps the figure at 44rem, which shrinks a banner
 * designed to be wide, and that cap exists there for the LOGO case handled below.
 */
.nv-shape-guide .nv-editorial .nv-article__figure,
.nv-shape-news .nv-editorial .nv-article__figure {
	max-inline-size: none;
	margin-block: 0 var(--wp--preset--spacing--lg);
}

/*
 * Photo sets: a 900x900 cover in front of the gallery that IS the content.
 *
 * Uncapped it rendered 1160x1160 — a square filling the entire first screen, upscaled from
 * 900px, in front of a grid of 570px thumbnails. And it is often the same picture: measured,
 * the featured image of 2 of the 4 photo-set posts (95 and 530) is one of the IDs inside that
 * post's own `[gallery]` shortcode. Capped and start-aligned, so it introduces the set instead
 * of competing with it. The duplication itself is an editorial cleanup, filed in
 * board/backend/content-needed/articles/.
 */
.nv-shape-gallery .nv-editorial .nv-article__figure {
	max-inline-size: min(100%, 30rem);
	margin-inline: 0;
	margin-block: 0 var(--wp--preset--spacing--lg);
}

.nv-editorial .nv-article__figure img {
	border-radius: var(--wp--custom--radius--lg);
}

/*
 * Client references: a 500x500 logo. Blown to the width of a reading column it is a blurry
 * upscale, and a logo on a white page with no frame floats. Cap it below its native size and
 * seat it on the quiet surface tone — the same framing the logo wall on "Нам доверяют" already
 * gives it, so the two pages agree. Start-aligned, not centred: the eyebrow, the title, the
 * meta line and the prose all begin at the same edge, and one centred panel in the middle of
 * that column reads as a stray.
 */
.nv-shape-client .nv-editorial .nv-article__figure {
	max-inline-size: min(100%, 20rem);
	margin-inline: 0;
	margin-block: 0 var(--wp--preset--spacing--md);
	padding: var(--wp--preset--spacing--sm);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	background-color: var(--wp--preset--color--surface);
}

.nv-shape-client .nv-editorial .nv-article__figure img {
	object-fit: contain;
}

/* ---------------------------------------------------------------------------
 * 4. THE READING COLUMN
 *
 * NOT ONE of the 30 published posts contains a single <h2> or <h3> — measured against
 * post_content, not guessed. The longest is 10,277 characters of unbroken paragraphs. Real
 * subheadings are content and are requested in board/backend/content-needed/articles/; what
 * typography can do about it, it does here: a shorter measure, more leading, and a clear
 * paragraph rhythm so the eye can find its place again after a break.
 *
 * 66ch, not content.css's 70ch. Roboto Condensed fits more characters per em than the
 * measure rule assumes, so the same character count runs physically longer.
 */
.nv-editorial .nv-prose {
	max-inline-size: 66ch;
	line-height: 1.7;
}

.nv-editorial .nv-prose p {
	margin-block: 0 var(--wp--preset--spacing--sm);
}

/*
 * The first paragraph becomes the standfirst.
 *
 * The database has ZERO hand-written excerpts, so there is no standfirst to render and one
 * must not be invented. But every article opens by stating its subject, so promoting that
 * real sentence to lead size gives the page the editorial entry it needs without writing a
 * word. If a hand-written standfirst is ever supplied it drops straight into this slot.
 */
.nv-editorial .nv-prose > .entry-content > p:first-child {
	font-size: var(--wp--preset--font-size--md);
	line-height: 1.55;
	color: var(--wp--preset--color--ink-soft);
	margin-block-end: var(--wp--preset--spacing--md);
}

/* A wide table in a 66ch column is unreadable; let it use the room and scroll if it must. */
.nv-editorial .nv-prose table {
	display: block;
	max-inline-size: 100%;
	overflow-x: auto;
}

/* ---------------------------------------------------------------------------
 * 5. WHAT COMES AFTER THE ARTICLE
 *
 * Three sections, in one order that is itself the argument: the buying step, then what to
 * read next, then adjacent navigation. A reader who has just finished "how to choose a
 * diameter" is closer to buying at that moment than at any other, so the product step goes
 * first — related reading is the thing that competes with it, not the thing that supports it.
 *
 * There is no mid-article CTA and no sticky bar. On a 54-product site one offer, placed where
 * the question has just been answered, is the whole of what is needed.
 * ------------------------------------------------------------------------ */

.nv-next,
.nv-adjacent {
	container-type: inline-size;
	margin-block-start: var(--wp--preset--spacing--xl);
	padding-block-start: var(--wp--preset--spacing--md);
	border-block-start: 1px solid var(--wp--preset--color--border);
}

.nv-next__title {
	margin: 0 0 var(--wp--preset--spacing--sm);
	font-size: var(--wp--preset--font-size--xl);
	line-height: 1.2;
	text-wrap: balance;
}

.nv-next__more {
	margin-block: var(--wp--preset--spacing--sm) 0;
}

.nv-textlink {
	display: inline-flex;
	align-items: center;
	/*
	 * `gap`, not the literal space in the markup. The label and the category name are two
	 * elements so TranslatePress can translate the name on its own (see the note in
	 * inc/article.php); inline-flex then discards the whitespace between them and the link
	 * rendered "Все товарыСферические обзорные зеркала для помещений" — seen on the page.
	 */
	gap: 0.35em;
	flex-wrap: wrap;
	min-block-size: 44px;
	font-weight: 700;
	color: var(--wp--preset--color--brand);
}

/* --- 5a. The buying step -------------------------------------------------- */

.nv-buys,
.nv-readnexts {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
	gap: var(--wp--preset--spacing--sm);
}

.nv-buy__link,
.nv-readnext__link {
	display: grid;
	grid-template-rows: auto 1fr;
	gap: var(--wp--preset--spacing--xs);
	block-size: 100%;
	/* The whole card is the target, so the 44px minimum is met many times over. */
	min-block-size: 44px;
	padding: var(--wp--preset--spacing--xs);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	transition: border-color var(--wp--custom--transition--base);
}

.nv-buy__link:hover,
.nv-buy__link:focus-visible,
.nv-readnext__link:hover,
.nv-readnext__link:focus-visible {
	border-color: var(--wp--preset--color--brand);
}

.nv-buy__media,
.nv-readnext__media {
	display: block;
	overflow: hidden;
	border-radius: var(--wp--custom--radius--md);
	background-color: var(--wp--preset--color--surface);
}

/*
 * `contain` on the product card: these are mirrors photographed on white, and a crop that
 * fills the box cuts the rim off a circular product — the shape a buyer is judging.
 */
.nv-buy__media img {
	display: block;
	inline-size: 100%;
	aspect-ratio: 1 / 1;
	object-fit: contain;
}

.nv-buy__text,
.nv-readnext__text {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--xxxs);
}

.nv-buy__name,
.nv-readnext__title {
	font-weight: 700;
	line-height: 1.25;
	text-wrap: balance;
}

/*
 * Price is brand green, the token DESIGN.md reserves for availability and the pre-order call
 * to action, so "this is the commerce signal" reads the same here as it does in the catalogue.
 */
.nv-buy__price {
	color: var(--wp--preset--color--accent);
	font-weight: 700;
}

.nv-buy__price del {
	color: var(--wp--preset--color--text-muted);
	font-weight: 400;
}

/* --- 5b. Read next -------------------------------------------------------- */

/*
 * The related cards carry the same 3.6:1 banners as the archive, so they get the same ratio.
 * `cover` rather than `contain` because a banner is already a crop and letterboxing a crop
 * inside a card just adds bars.
 */
.nv-readnext__media img {
	display: block;
	inline-size: 100%;
	aspect-ratio: 1140 / 317;
	object-fit: cover;
}

/*
 * …except on a client or photo-set page, where "read next" is more clients and more photo
 * sets: square logos and square covers, so a square frame and `contain`, matching the archive
 * those cards came from.
 */
.nv-shape-client .nv-readnext__media img,
.nv-shape-gallery .nv-readnext__media img {
	aspect-ratio: 1 / 1;
	object-fit: contain;
}

.nv-readnext__meta {
	color: var(--wp--preset--color--text-muted);
	font-size: var(--wp--preset--font-size--sm);
}

/* --- 5c. Previous / next -------------------------------------------------- */

.nv-adjacent {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
	gap: var(--wp--preset--spacing--sm);
}

.nv-adjacent__link {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--xxxs);
	justify-content: center;
	min-block-size: 44px;
	padding: var(--wp--preset--spacing--xs);
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	transition: background-color var(--wp--custom--transition--base);
}

.nv-adjacent__link:hover,
.nv-adjacent__link:focus-visible {
	background-color: var(--wp--preset--color--surface);
}

/* The "next" card sits at the end of the row even when there is no "previous". */
.nv-adjacent__link--next {
	text-align: end;
	grid-column: -2;
}

/*
 * Once the pair stacks there is no "other end" to align to, and a right-ragged block under a
 * left-ragged one just looks like a mistake. Measured single-column at a real 390px viewport.
 */
@container (max-width: 34rem) {
	.nv-adjacent__link--next {
		text-align: start;
	}
}

.nv-adjacent__dir {
	color: var(--wp--preset--color--text-muted);
	font-size: var(--wp--preset--font-size--xs);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.nv-adjacent__title {
	font-weight: 700;
	line-height: 1.3;
}

/* ---------------------------------------------------------------------------
 * 6. THE ARCHIVES
 *
 * Two shapes, one template. Which one a category gets is a property of its CONTENT, and
 * WordPress already emits the `category-<slug>` body class that says which — so there is no
 * second template and no markup fork, only a different set of rules reading the same markup.
 * ------------------------------------------------------------------------ */

/*
 * The head is NOT capped and NOT centred.
 *
 * It was, at 60ch, and rendered wrong: WordPress's constrained layout gives every child of a
 * constrained group `margin-inline: auto` with `!important`, so a capped heading became a
 * 474px column floated to x=627 while the cards below it started at x=224 — measured in the
 * browser, not guessed. The fix is in the TEMPLATE, not here: both head groups in
 * archive.html and single.html declare `layout: default` instead of `constrained`, so no auto
 * margin is generated in the first place and this file does not have to out-shout an
 * `!important`. The heading runs the width of the list it introduces; only the intro gets a
 * measure, and it starts at the same edge as the cards.
 */
/*
 * The head and the cards were two blocks of text with nothing but a gap between them, which
 * read as one continuous column — the intro paragraph and the first card's excerpt are the
 * same size and colour. A hairline closes the section: it says "the description ends here,
 * the list starts below" without adding a heavy band or another heading.
 *
 * The rule fades out toward the right rather than running edge to edge, so it separates
 * without drawing a box around the page. Padding above it and margin below it are unequal on
 * purpose: the line belongs to the head it closes, so it sits nearer to it.
 */
.nv-editorial-list .nv-listing__head {
	position: relative;
	padding-block-end: var(--wp--preset--spacing--sm);
	margin-block-end: var(--wp--preset--spacing--lg);
}

.nv-editorial-list .nv-listing__head::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-end: 0;
	block-size: 1px;
	background-image: linear-gradient(
		to right,
		var(--wp--preset--color--border) 0%,
		var(--wp--preset--color--border) 45%,
		transparent 100%
	);
}

.nv-editorial-list .nv-listing__title {
	line-height: 1.05;
	letter-spacing: -0.01em;
}

/*
 * A standfirst, not a paragraph of body copy. It was set at exactly the size and colour of a
 * card excerpt, so the eye had no way to tell the section's description from the first
 * article's summary — muted and roomier, it reads as introduction and hands off to the list.
 */
.nv-editorial-list .nv-listing__intro {
	max-inline-size: 60ch;
	margin-block: var(--wp--preset--spacing--xs) 0;
	color: var(--wp--preset--color--text-muted);
	line-height: 1.65;
}

/*
 * TEXT ARCHIVES — /category/stati/ and /category/novosti/.
 *
 * A stacked card, not the thumbnail-left media row content.css defaults to. That row gives
 * the image a 12rem column; a 3.6:1 banner in a 12rem column is a 12rem x 3.3rem sliver that
 * communicates nothing. Full-width on top, the same banner is the strongest thing on the card.
 *
 * Two columns, from a container query on the LIST, so the count follows the space the list
 * has rather than the width of the window.
 */
/*
 * `container-type` goes HERE, on the <main>, not on the list.
 *
 * content.css already makes `.nv-cards` a container, which serves its rules because those
 * target `.nv-card` — a descendant. An element cannot query ITSELF, so a rule that changes
 * `.nv-cards`'s own column count has to query an ancestor. The first version of this file put
 * the query on `.nv-cards` and the two-column layout silently never applied: measured
 * `grid-template-columns: 1280px` at a 1728px viewport.
 */
.nv-editorial-list {
	container-type: inline-size;
}

.nv-editorial-list .nv-cards {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--wp--preset--spacing--md);
}

/*
 * Equal card heights, and cards that start at the top of their cell.
 *
 * Both are one bug. `core/post-template` renders its <ul> with `is-layout-flow`, whose global
 * stylesheet puts `margin-block-start` on every child AFTER the first. That is right for a
 * stacked list and wrong for a grid: it pushes items 2..n down inside their own cells, which
 * measured as a 24px step between the two cards of a row on /category/stati/ and a 30px step
 * across the client logo grid, where the first card also came out 356px tall against 326px for
 * its four neighbours. Zeroing the margin and asking for the full cell height fixes the
 * alignment and the height together — verified in the browser, not assumed. Same class of
 * defect as known issue 6 on the catalogue.
 */
.nv-editorial-list .nv-cards > li {
	margin-block-start: 0;
	block-size: 100%;
}

.nv-editorial-list .nv-card {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--xs);
	grid-template-columns: none;
	block-size: 100%;
	padding: 0 0 var(--wp--preset--spacing--md);
}

/*
 * `inline-size: 100%` is load-bearing. The featured-image block renders a <figure>, and
 * something ahead of this file in the cascade sizes that figure to the image's intrinsic
 * 1140px rather than to the card — measured: card 1280px, figure 1140px, a 140px step at the
 * right-hand edge of every card in the list.
 */
.nv-editorial-list .nv-card__media {
	inline-size: 100%;
	max-inline-size: none;
	order: -1;
}

.nv-editorial-list .nv-card__media img {
	inline-size: 100%;
	block-size: auto;
	aspect-ratio: 1140 / 317;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--lg);
}

.nv-editorial-list .nv-card__text {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--xxxs);
}

.nv-editorial-list .nv-card__title {
	font-size: var(--wp--preset--font-size--xl);
	line-height: 1.15;
	letter-spacing: -0.01em;
}

.nv-editorial-list .nv-card__excerpt {
	max-inline-size: 60ch;
	line-height: 1.55;
}

@container (min-width: 46rem) {
	.nv-editorial-list .nv-cards {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--wp--preset--spacing--lg) var(--wp--preset--spacing--md);
	}
}

/*
 * IMAGE-LED ARCHIVES — /category/clients/ and /category/photogallery/.
 *
 * Square logos and square gallery covers, so a square frame and `contain`: cropping a client's
 * logo to fill a box cuts the brand in half. content.css already establishes this grid; the
 * refinements here are the square frame, the centred logo, and killing the banner ratio rule
 * above, which must not reach these cards.
 */
.category-clients .nv-editorial-list .nv-card,
.category-photogallery .nv-editorial-list .nv-card {
	padding: var(--wp--preset--spacing--xs);
	gap: var(--wp--preset--spacing--xxs);
}

.category-clients .nv-editorial-list .nv-card__media img,
.category-photogallery .nv-editorial-list .nv-card__media img {
	aspect-ratio: 1 / 1;
	object-fit: contain;
	border-radius: var(--wp--custom--radius--md);
}

.category-clients .nv-editorial-list .nv-card__title,
.category-photogallery .nv-editorial-list .nv-card__title {
	font-size: var(--wp--preset--font-size--base);
	text-align: center;
}

/* The whole card is the link on a logo grid, so the title needs no second underline. */
.category-clients .nv-editorial-list .nv-card__title a,
.category-photogallery .nv-editorial-list .nv-card__title a {
	text-decoration: none;
}

/* The two-column text rule must not reach the logo grid. */
@container (min-width: 46rem) {
	/*
	 * `auto-fit`, not `auto-fill`. Photogallery has four posts; auto-fill held five 13rem
	 * tracks open at 1160px and rendered four 184px thumbnails with a dead column beside them.
	 * auto-fit collapses the track that has nothing in it and the four covers use the full
	 * width. The 16-item client grid is unaffected — every track there has cards in it, so
	 * there is nothing to collapse.
	 */
	.category-clients .nv-editorial-list .nv-cards,
	.category-photogallery .nv-editorial-list .nv-cards {
		grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
		gap: var(--wp--preset--spacing--sm);
	}
}

/* ---------------------------------------------------------------------------
 * 7. PLACEHOLDERS
 *
 * Deliberately loud. A placeholder that blends in is a placeholder that ships. Every one of
 * these has a matching entry in board/backend/content-needed/articles/articles.md.
 * ------------------------------------------------------------------------ */

.nv-placeholder {
	padding: var(--wp--preset--spacing--xs);
	border: 1px dashed var(--wp--preset--color--brand);
	border-radius: var(--wp--custom--radius--md);
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--brand-darker);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
}

/* ---------------------------------------------------------------------------
 * 8. PAGINATION
 *
 * The editorial archives page in fours (NIKOLVIVA_ARCHIVE_PER_PAGE), so the pagination is
 * something a reader uses on nearly every visit rather than a rare footer accessory. It gets
 * a real control strip: 44px targets, a filled current page, arrows that read as buttons, and
 * a "Страница 2 из 7" line so the reader knows the size of the section before clicking.
 * ------------------------------------------------------------------------ */

.nv-editorial-list .nv-pagination {
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--xxs);
	margin-block-start: var(--wp--preset--spacing--lg);
}

.nv-editorial-list .nv-pagination a,
.nv-editorial-list .nv-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-inline-size: 44px;
	min-block-size: 44px;
	padding-inline: var(--wp--preset--spacing--xxs);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--md);
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	line-height: 1;
	text-decoration: none;
	transition: background-color var(--wp--custom--transition--base),
		border-color var(--wp--custom--transition--base),
		color var(--wp--custom--transition--base);
}

.nv-editorial-list .nv-pagination a:hover,
.nv-editorial-list .nv-pagination a:focus-visible {
	border-color: var(--wp--preset--color--brand);
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--brand-darker);
}

/* You are here. Filled, not merely bolder — at a glance the eye finds one solid block. */
.nv-editorial-list .nv-pagination .page-numbers.current {
	border-color: var(--wp--preset--color--brand);
	background-color: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--base);
}

/* The "…" between the window and the last page is a label, not a target. */
.nv-editorial-list .nv-pagination .page-numbers.dots {
	min-inline-size: 1.5rem;
	border-color: transparent;
	background: none;
	color: var(--wp--preset--color--text-muted);
}

/* Prev / next carry a word as well as an arrow, so they are wider than a number. */
.nv-editorial-list .nv-pagination .wp-block-query-pagination-previous,
.nv-editorial-list .nv-pagination .wp-block-query-pagination-next {
	gap: var(--wp--preset--spacing--xxxs);
}

.nv-editorial-list .nv-pagination .wp-block-query-pagination-previous-arrow,
.nv-editorial-list .nv-pagination .wp-block-query-pagination-next-arrow {
	margin: 0;
	font-size: 1.1em;
	line-height: 1;
}

/*
 * Phones: the word beside the arrow is what pushes the strip onto three rows at 360px. The
 * arrow alone is unambiguous next to a row of page numbers, and the link keeps its full 44px
 * target either way.
 */
@media (max-width: 30rem) {
	.nv-editorial-list .nv-pagination .wp-block-query-pagination-previous,
	.nv-editorial-list .nv-pagination .wp-block-query-pagination-next {
		font-size: 0;
	}

	.nv-editorial-list .nv-pagination .wp-block-query-pagination-previous-arrow,
	.nv-editorial-list .nv-pagination .wp-block-query-pagination-next-arrow {
		font-size: 1.25rem;
	}
}

.nv-editorial-list .nv-pagination__info {
	margin-block: var(--wp--preset--spacing--xs) 0;
	color: var(--wp--preset--color--text-muted);
	font-size: var(--wp--preset--font-size--sm);
	text-align: center;
}

/* ---------------------------------------------------------------------------
 * 9. PHOTO SETS — the [gallery] on /category/photogallery/ posts
 *
 * These posts are one paragraph plus twenty photographs, so the photographs ARE the page.
 * They were rendering as a single 240px-wide column stacked twenty deep: the markup comes
 * from photoswipe-masonry, whose masonry JS is switched off (`use_masonry_` is empty in the
 * wrapper class), leaving floated figures carrying inline `width:285px` inside a 554px
 * reading measure. Four columns were declared and one was drawn.
 *
 * Fixed in three parts: escape the measure, replace the floats with a grid, and make the
 * captions legible — they carry the only description each photo gets ("Дорожнє дзеркало без
 * козирка при виїзді з двору"), so they are content, not decoration.
 * ------------------------------------------------------------------------ */

/*
 * A photo set is not prose and must not be capped at the prose measure. `.nv-prose` caps its
 * children at 554px while the article body around it is 1280px, so the gallery is pulled back
 * out to the body width with the standard centred break-out: the element is given the width we
 * want, then margin-inline pulls it left by half the difference. `50%` here resolves against
 * the 554px containing block, which is exactly the centre line we are expanding around.
 *
 * The width is also clamped to the viewport minus the shell's gutter so the break-out can
 * never introduce a horizontal scrollbar on a narrow screen.
 */
.nv-editorial .psgal_wrap {
	--nv-gallery-w: min(1280px, calc(100vw - 2 * var(--wp--preset--spacing--md)));

	inline-size: var(--nv-gallery-w);
	max-inline-size: none;
	margin-inline: calc(50% - var(--nv-gallery-w) / 2);
	margin-block: var(--wp--preset--spacing--lg);
}

/*
 * The grid derives its column count from the space available rather than from the `columns="4"`
 * written into the shortcode in 2017 — the same photo set then works at every width without a
 * second breakpoint. auto-fit, not auto-fill: a set of 20 fills every track, but the 4-photo
 * sets in this category would otherwise hold empty tracks open.
 */
.nv-editorial .psgal {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
	gap: var(--wp--preset--spacing--sm);
}

/*
 * `!important` IS DELIBERATE, and only here.
 *
 * photoswipe-masonry writes `style="width:285px"` onto every <figure> and
 * `style="height:275px"` onto every <a> as INLINE attributes, from PHP, per request. Inline
 * styles outrank any selector, so there is no specificity a stylesheet can reach for — the
 * only way to hand sizing back to the grid is to out-rank the attribute itself. The plugin is
 * not edited and nothing here breaks when it updates.
 */
.nv-editorial .psgal .msnry_items {
	inline-size: auto !important;
	display: flex;
	flex-direction: column;
	margin: 0;
}

.nv-editorial .psgal .msnry_items > a {
	block-size: auto !important;
	display: block;
	position: relative;
	overflow: hidden;
	aspect-ratio: 1;
	border-radius: var(--wp--custom--radius--lg);
	background-color: var(--wp--preset--color--surface);
}

/*
 * `cover` on a square frame. Every photo in these sets is already 900x900, so the crop is a
 * no-op today; it is here so a future non-square upload cannot break the row alignment.
 */
.nv-editorial .psgal .msnry_thumb {
	display: block;
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	transition: transform 320ms ease;
}

.nv-editorial .psgal .msnry_items > a:hover .msnry_thumb,
.nv-editorial .psgal .msnry_items > a:focus-visible .msnry_thumb {
	transform: scale(1.04);
}

.nv-editorial .psgal .msnry_items > a:focus-visible {
	outline: var(--wp--custom--focus--width) solid var(--wp--preset--color--brand);
	outline-offset: var(--wp--custom--focus--offset);
}

/*
 * The caption is the photograph's only description — where the mirror is, and what it is
 * watching. It was rendering at the plugin's own tiny size and clipped. Left-aligned under the
 * image at the theme's small size, it reads as a label belonging to the photo above.
 */
.nv-editorial .psgal .photoswipe-gallery-caption {
	padding-block-start: var(--wp--preset--spacing--xxs);
	color: var(--wp--preset--color--text-muted);
	font-size: var(--wp--preset--font-size--sm);
	line-height: 1.45;
	text-align: start;
}

@media (prefers-reduced-motion: reduce) {
	.nv-editorial .psgal .msnry_thumb {
		transition: none;
	}

	.nv-editorial .psgal .msnry_items > a:hover .msnry_thumb {
		transform: none;
	}
}
