/*
Theme Name: Betty Adamou
Theme URI: https://www.bettyadamou.com/
Author: Porter Valley Technology Limited
Author URI: https://portervalley.tech/
Description: Block theme for Betty Adamou, built from the Ghost relaunch theme (Source 1.7.6 adapted, betty.css). Playfair Display and Figtree, a dark stage palette for bands, tiles and footer, and system dark mode. Everything editable lives in theme.json (Styles), the templates and the patterns; this file holds only what theme.json cannot say.
Requires at least: 7.0
Tested up to: 7.1
Requires PHP: 8.2
Version: 0.2.0
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: betty-adamou
Tags: block-patterns, full-site-editing, portfolio, blog, custom-colors, editor-style, wide-blocks
*/

/*
 * The exhaustive list of rules lives in docs/contracts.md ("style.css
 * rules"). Every colour is a palette custom property from theme.json, so a
 * palette change in Styles flows through all of them. Line numbers refer to
 * bettyadamou-com theme/assets/css/betty.css.
 */

/* R1. Dark mode (betty.css 59-71). The system scheme remaps the light
 * tokens onto the stage tokens; no toggle (design decision 2026-10-07).
 * html:root outranks the :root block that global styles prints, so the
 * remap wins whatever order the stylesheets load in, and a Styles edit to
 * any stage colour still flows through. */
@media (prefers-color-scheme: dark) {
	html:root {
		--wp--preset--color--base: var(--wp--preset--color--stage-bg);
		--wp--preset--color--surface: var(--wp--preset--color--stage-surface);
		--wp--preset--color--contrast: var(--wp--preset--color--stage-text);
		--wp--preset--color--muted: var(--wp--preset--color--stage-muted);
		--wp--preset--color--line: var(--wp--preset--color--stage-border);
		--wp--preset--color--accent-ink: var(--wp--preset--color--stage-accent);
		--wp--preset--color--on-accent-ink: var(--wp--preset--color--ink);
		color-scheme: dark;
	}
}

/* R2. Stage bands (betty.css 205-222, .ba-stage). Inside a dark band or a
 * CTA band the light tokens point at the stage tokens in BOTH schemes, so
 * any block Betty drops in (text, link, button, separator) follows the band
 * without its own colour settings. The band's own background and text
 * colour are block settings (theme.json variations and the patterns). */
.is-style-dark-band,
.is-style-cta-band {
	--wp--preset--color--base: var(--wp--preset--color--stage-bg);
	--wp--preset--color--surface: var(--wp--preset--color--stage-surface);
	--wp--preset--color--contrast: var(--wp--preset--color--stage-text);
	--wp--preset--color--muted: var(--wp--preset--color--stage-muted);
	--wp--preset--color--line: var(--wp--preset--color--stage-border);
	--wp--preset--color--accent-ink: var(--wp--preset--color--stage-accent);
	--wp--preset--color--on-accent-ink: var(--wp--preset--color--ink);
}

/* R3. Tile grid on phones (betty.css 659-667, 698-702). Two columns under
 * 768px and an odd last tile spanning the row (one column again under
 * 360px). Core's own grid collapses to ONE column under 600px and has no
 * "span the odd last item" setting, so this stays CSS. Selector: the Query
 * block carrying the class ba-tiles (Advanced > Additional CSS class). */
@media (max-width: 767px) {
	.wp-block-query.ba-tiles .wp-block-post-template.is-layout-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 6px;
	}

	.wp-block-query.ba-tiles .wp-block-post-template.is-layout-grid > li:last-child:nth-child(odd) {
		grid-column: 1 / -1;
	}
}

@media (max-width: 359px) {
	.wp-block-query.ba-tiles .wp-block-post-template.is-layout-grid > li:last-child:nth-child(odd) {
		grid-column: auto;
	}
}

/* R4. Tile: one link, hover, phone caption (betty.css 532-546, 598-605,
 * 634-657, 680-687, 704-728). The Cover block (class ba-tile) is the 4:3
 * frame with the featured image and the scrim gradient; its title link is
 * stretched over the whole tile (the ::after reaches past the inner
 * container and the Cover clips it), so the tile is one target whose
 * accessible name is the title. Phone padding, the hidden kicker and the
 * smaller muted caption are per-viewport block settings in the pattern;
 * only the two-line clamp of the caption and Ghost's 2px phone gap
 * between title, kicker and caption (the Cover's block gap is 6px at every
 * width) are CSS. The tile sits on the stage surface (Ghost .ba-tile), so
 * a transparent picture (Celebration, Gamification) shows it, not the
 * page colour. */
.ba-tile {
	overflow: hidden;
	isolation: isolate;
	background-color: var(--wp--preset--color--stage-surface);
}

.ba-tile .wp-block-post-title a::after {
	content: "";
	position: absolute;
	top: -100vh;
	right: -100vw;
	bottom: -100vh;
	left: -100vw;
	z-index: 2;
}

.ba-tile .wp-block-post-title a {
	text-decoration: underline transparent;
	text-decoration-thickness: 2px;
	text-underline-offset: 5px;
	transition: text-decoration-color 240ms ease-out;
}

.ba-tile:hover .wp-block-post-title a {
	text-decoration-color: var(--wp--preset--color--stage-accent);
}

.ba-tile .wp-block-cover__image-background {
	transition: transform 240ms ease-out;
}

.ba-tile:hover .wp-block-cover__image-background {
	transform: scale(1.03);
}

.ba-tile:has(a:focus-visible) {
	outline: 3px solid var(--wp--preset--color--focus);
	outline-offset: -3px;
}

.ba-tile a:focus-visible {
	outline: 0;
}

/* The caption ends in an accent arrow that shows on hover (betty.css
 * 618-633, 655-657, 689-691: .ba-tile-caption, .ba-tile-arrow); it keeps
 * its room when hidden, so the caption wraps as on Ghost. Not on phones. */
.ba-tile .wp-block-post-excerpt {
	display: flex;
	justify-content: space-between;
	gap: 12px;
}

.ba-tile .wp-block-post-excerpt::after {
	content: "\2192";
	flex-shrink: 0;
	white-space: nowrap;
	color: var(--wp--preset--color--stage-accent);
	opacity: 0;
	transition: opacity 240ms ease-out;
}

.ba-tile:hover .wp-block-post-excerpt::after {
	opacity: 1;
}

@media (max-width: 767px) {
	.ba-tile .wp-block-cover__inner-container > * + * {
		margin-block-start: 2px;
	}

	.ba-tile .wp-block-post-excerpt::after {
		content: none;
	}

	.ba-tile .wp-block-post-excerpt {
		display: -webkit-box;
		-webkit-box-orient: vertical;
		-webkit-line-clamp: 2;
		overflow: hidden;
	}
}

@media (prefers-reduced-motion: reduce) {
	.ba-tile .wp-block-cover__image-background,
	.ba-tile .wp-block-post-excerpt::after,
	.ba-tile .wp-block-post-title a {
		transition: none;
	}

	.ba-tile:hover .wp-block-cover__image-background {
		transform: none;
	}
}

/* R5. Artwork tile (betty.css 549-569, 581-583, tile.hbs): a page with the
 * site_role term "artwork" (class is-artwork on its list item, from the
 * ba-site mu-plugin) shows its picture whole, never cropped, over a
 * blurred, darkened copy that fills the tile. The Cover's own featured
 * image is the blurred copy; the second Featured Image block in the tile
 * (class ba-tile-art) is the whole work, and stays hidden on every other
 * tile. The scrim switches to the tile-scrim-artwork gradient preset (it
 * starts below the picture); preset gradient classes carry !important.
 * The inner container steps out of positioning so the work can fill the
 * tile, and the text keeps its place above the scrim. The blurred copy is
 * 112% high but only 100% wide: Source's img max-width: 100% clamps
 * Ghost's backdrop width. */
.ba-tile .ba-tile-art {
	display: none;
}

.is-artwork .ba-tile img.wp-block-cover__image-background {
	top: -6%;
	right: auto;
	bottom: auto;
	left: -6%;
	width: 100%;
	height: 112%;
	object-fit: cover;
	filter: blur(14px) brightness(0.5);
}

.is-artwork .ba-tile .wp-block-cover__background {
	background: var(--wp--preset--gradient--tile-scrim-artwork) !important;
}

.is-artwork .ba-tile .wp-block-cover__inner-container {
	position: static;
}

.is-artwork .ba-tile .wp-block-cover__inner-container > :not(.ba-tile-art) {
	position: relative;
	z-index: 2;
}

/* The title (its link stretched over the tile, R4) stays the top layer. */
.is-artwork .ba-tile .wp-block-cover__inner-container > .wp-block-post-title {
	z-index: 3;
}

.is-artwork .ba-tile .ba-tile-art {
	display: block;
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 0;
	margin: 0;
	transition: transform 240ms ease-out;
}

.is-artwork .ba-tile .ba-tile-art img {
	box-sizing: border-box;
	width: 100%;
	height: 100%;
	padding: 6% 6% 38%;
	object-fit: contain;
}

.is-artwork .ba-tile:hover .ba-tile-art {
	transform: scale(1.03);
}

@media (prefers-reduced-motion: reduce) {
	.is-artwork .ba-tile .ba-tile-art {
		transition: none;
	}

	.is-artwork .ba-tile:hover .ba-tile-art {
		transform: none;
	}
}

/* R6. Uncropped and Cover block styles (betty.css 1165-1175, 1203-1220;
 * Ghost #artwork / #cover). Uncropped: the work whole in a 4:3 frame on the
 * surface colour; Cover: the frame filled. In a Gallery: two columns from
 * 600px to 1023px, and under 600px one column with each work at its own
 * proportions. The :not(#individual-image) matches the weight of core's
 * own gallery selectors. */
.wp-block-image.is-style-uncropped img {
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 3;
	object-fit: contain;
	background: var(--wp--preset--color--surface);
}

.wp-block-image.is-style-cover img {
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

@media (min-width: 600px) {
	.wp-block-gallery.is-style-uncropped.has-nested-images figure.wp-block-image:not(#individual-image) img {
		flex: none;
		width: 100%;
		height: auto;
		aspect-ratio: 4 / 3;
		object-fit: contain;
		background: var(--wp--preset--color--surface);
	}

	.wp-block-gallery.is-style-cover.has-nested-images figure.wp-block-image:not(#individual-image) img {
		flex: none;
		width: 100%;
		height: auto;
		aspect-ratio: 4 / 3;
		object-fit: cover;
	}
}

/* One work's own style wins inside a styled gallery (Betty test D2): Image
 * > Styles > "Uncropped" on a picture in a "Cover" gallery shows that work
 * whole in the frame, and "Cover" on a picture in an "Uncropped" gallery
 * fills its frame. One class more than the gallery rules above, so the
 * picture's choice wins whatever the order. Under 600px every work in the
 * gallery is at its own proportions (Ghost's one-column gallery), so the
 * single-image 4:3 frame above does not apply there either. */
@media (min-width: 600px) {
	.wp-block-gallery.is-style-cover.has-nested-images figure.wp-block-image.is-style-uncropped:not(#individual-image) img {
		object-fit: contain;
		background: var(--wp--preset--color--surface);
	}

	.wp-block-gallery.is-style-uncropped.has-nested-images figure.wp-block-image.is-style-cover:not(#individual-image) img {
		object-fit: cover;
	}
}

@media (max-width: 599px) {
	.wp-block-gallery:is(.is-style-uncropped, .is-style-cover).has-nested-images figure.wp-block-image:is(.is-style-uncropped, .is-style-cover):not(#individual-image) img {
		height: auto;
		aspect-ratio: auto;
		background: none;
	}
}

/* A short last row keeps the column width (Ghost's grid leaves the cells
 * empty); core grows the remaining works to fill the row. */
.wp-block-gallery:is(.is-style-uncropped, .is-style-cover).has-nested-images figure.wp-block-image:not(#individual-image) {
	flex-grow: 0;
}

@media (min-width: 600px) and (max-width: 1023px) {
	.wp-block-gallery:is(.is-style-uncropped, .is-style-cover).has-nested-images figure.wp-block-image:not(#individual-image) {
		width: calc(50% - var(--wp--style--unstable-gallery-gap, 16px) / 2);
	}
}

@media (max-width: 599px) {
	.wp-block-gallery:is(.is-style-uncropped, .is-style-cover).has-nested-images figure.wp-block-image:not(#individual-image) {
		width: 100%;
	}
}

/* R7. Logo strip block style (betty.css 742-762, 1036-1042, dark 73-78;
 * Ghost gallery card rows): a Gallery becomes rows of three greyscale
 * logos, at most 56px high, inverted in dark mode. Ghost splits a gallery
 * into rows of three at every width and gives each image a share of its
 * row in proportion to its aspect ratio (Koenig's flex: <ratio> 1 0%),
 * the logo drawn at the left of its share; 44px between shares (38px at
 * 600px and under) and 12px between rows (6px). Where the browser reads
 * typed attr(), the image itself is the flex item, grown by width/height
 * from its own attributes (WordPress prints them on every attachment), and
 * a zero-height break after every third logo starts the next row. Other
 * browsers, and the editors (whose block wrappers must keep their boxes),
 * get the equal-thirds fallback: each logo at the left of a third of the
 * row less 12px gaps (core drops to two per row on phones). */
.wp-block-gallery.is-style-logo-strip.has-nested-images {
	align-items: center;
	gap: 12px;
}

.wp-block-gallery.is-style-logo-strip.has-nested-images figure.wp-block-image:not(#individual-image) {
	flex: 0 0 auto;
	align-items: flex-start;
	width: calc((100% - 24px) / 3);
	margin: 0;
}

.wp-block-gallery.is-style-logo-strip.has-nested-images figure.wp-block-image:not(#individual-image) img {
	flex: none;
	width: auto;
	max-width: 100%;
	height: auto;
	max-height: 56px;
	object-fit: contain;
	filter: grayscale(1);
	opacity: 0.8;
}

@supports (flex-grow: attr(width type(<number>), 1)) {
	.wp-block-gallery.is-style-logo-strip.has-nested-images:not(.block-editor-block-list__block) {
		position: relative;
		gap: 6px 44px;
	}

	.wp-block-gallery.is-style-logo-strip.has-nested-images figure.wp-block-image:not(#individual-image, .block-editor-block-list__block) {
		display: contents;
	}

	.wp-block-gallery.is-style-logo-strip.has-nested-images figure.wp-block-image:not(#individual-image, .block-editor-block-list__block):nth-child(3n of figure):not(:nth-last-child(1 of figure))::after {
		content: "";
		flex: 0 0 100%;
		height: 0;
	}

	.wp-block-gallery.is-style-logo-strip.has-nested-images figure.wp-block-image:not(#individual-image, .block-editor-block-list__block) img {
		flex: calc(attr(width type(<number>), 1) / attr(height type(<number>), 1)) 1 0%;
		min-width: 0;
		max-width: none;
		object-position: left center;
	}

	.wp-block-gallery.is-style-logo-strip.has-nested-images .lightbox-trigger {
		display: none;
	}
}

@media (max-width: 600px) {
	@supports (flex-grow: attr(width type(<number>), 1)) {
		.wp-block-gallery.is-style-logo-strip.has-nested-images:not(.block-editor-block-list__block) {
			gap: 3px 38px;
		}
	}
}

@media (prefers-color-scheme: dark) {
	.wp-block-gallery.is-style-logo-strip.has-nested-images figure.wp-block-image:not(#individual-image) img {
		filter: grayscale(1) invert(1);
	}
}

/* R7a. Greyscale block style (betty.css 1036-1042; Ghost gallery cards
 * on a page tagged #press): the default gallery rows (RP5 keeps them for
 * this style), every picture greyscale at 0.85 opacity in BOTH schemes.
 * betty.css 73-78 also lists an inverted dark-mode rule, but the light
 * rule comes later with the same weight and wins, so Ghost renders the
 * press clippings (photographs, not logos) uninverted in dark mode too
 * (measured on staging). No filter setting exists in Styles. */
.wp-block-gallery.is-style-greyscale.has-nested-images figure.wp-block-image:not(#individual-image) img {
	filter: grayscale(1);
	opacity: 0.85;
}

/* R8. Header (betty.css 259-375, Source .gh-search / .gh-burger). The
 * search button is Ghost's 32px icon button holding Ghost's 20px outline
 * magnifier (Source icons/search.hbs, stroke 2, handle down right), and the
 * phone menu button draws Ghost's burger (icons/burger.hbs: three 18px
 * round-capped lines); core prints its own glyphs with no setting for
 * either, so the core paths are hidden and the svg box paints currentColor
 * through a mask of Ghost's shape (the colour still follows the block's
 * text colour and the scheme). On phones the row is logo | search |
 * Subscribe | menu button, clustered right with an 8px gap and a 44px menu
 * button: flex order, auto margins and the menu button's size have no
 * block setting, so the Navigation block (its menu button on phones) moves
 * to the end of the row and stops filling it, and the actions group (class
 * ba-header-actions) takes the free space on its left; an opened search
 * field stands in for the Subscribe button there. Since 2026-10-13 the
 * header has no Navigation block (no links, no menu button), and "Sign in"
 * shows on phones too (it fits at 320px). Selector: the header
 * part's row, class ba-header-row. */
/* Ghost's search button pulls 2px into its neighbours, and Source sets it
 * 24px from "Sign in" (the actions group's gap is 20px). */
.ba-header-row .wp-block-search {
	margin-inline: -2px 2px;
}

.ba-header-row .wp-block-search__button {
	width: 32px;
	height: 32px;
	min-width: 0;
	margin: 0;
	padding: 6px;
	box-sizing: border-box;
}

.ba-header-row .wp-block-search__button svg {
	width: 20px;
	height: 20px;
	min-width: 0;
	min-height: 0;
	background-color: currentColor;
	-webkit-mask: 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='M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
	mask: 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='M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}

.ba-header-row .wp-block-search__button svg > *,
.ba-header-row .wp-block-navigation__responsive-container-open svg > * {
	display: none;
}

.ba-header-row .wp-block-navigation__responsive-container-open svg {
	background-color: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128ZM40,72H216a8,8,0,0,0,0-16H40a8,8,0,0,0,0,16ZM216,184H40a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128ZM40,72H216a8,8,0,0,0,0-16H40a8,8,0,0,0,0,16ZM216,184H40a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}

.ba-header-row .wp-block-search__input {
	height: 32px;
	padding-block: 0;
}

@media (max-width: 767px) {
	.wp-block-group.ba-header-row,
	.wp-block-group.ba-header-actions {
		column-gap: 8px;
	}

	.ba-header-row > .wp-block-navigation {
		order: 9;
		flex: 0 0 auto;
	}

	.ba-header-row > .ba-header-actions {
		margin-left: auto;
	}

	.ba-header-row .wp-block-search {
		margin-inline-end: -2px;
	}

	.ba-header-row .wp-block-navigation__responsive-container-open {
		margin: 0 -7px 0 4px;
		padding: 10px;
	}

	/* An opened search field takes the Subscribe button's place. */
	.ba-header-actions:has(.wp-block-search:not(.wp-block-search__searchfield-hidden)) > .wp-block-buttons {
		display: none;
	}

	.ba-header-row .wp-block-search:not(.wp-block-search__searchfield-hidden) .wp-block-search__input {
		width: 180px;
	}
}

/* R8a. Footer (betty.css 1434-1522, Source .gh-footer-*). The long-tail
 * menu (class ba-footer-nav) has no hover underline: the header's underline
 * rule in theme.json reaches every Navigation block. The small social icon
 * is Ghost's 20px (core's sizes are 16 and 24), and the X icon is Ghost's
 * solid X mark (Source icons/x.hbs) in place of core's outline one, drawn
 * as in R8: core's path hidden, the svg box painting currentColor through
 * a mask of Ghost's shape (no block setting picks an icon's artwork). On
 * phones the bar is one column as on Ghost: logo, the icons on their own
 * row at the right, then the copyright line (class ba-footer-meta); flex direction and a
 * per-viewport gap have no block setting. Selectors: the footer part's
 * classes ba-footer-nav, ba-footer-bar, ba-footer-brand, ba-footer-meta. */
.ba-footer-nav .wp-block-navigation-item__content {
	padding-bottom: 0;
	border-bottom: 0;
}

.ba-footer-bar .wp-block-social-links.has-small-icon-size {
	font-size: 20px;
}

.ba-footer-bar .wp-social-link-x svg {
	background-color: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}

.ba-footer-bar .wp-social-link-x svg > * {
	display: none;
}

@media (max-width: 767px) {
	.wp-block-group.ba-footer-brand {
		flex-direction: column;
		align-items: flex-start;
	}

	.ba-footer-brand > .wp-block-social-links {
		align-self: flex-end;
	}

	.ba-footer-bar > .ba-footer-meta {
		margin-block-start: 56px;
	}
}

/* R8b. Signup form (betty.css 840-856, Source .gh-form): MailPoet's email
 * field and button (betty-adamou/signup-form) become one 56px field on the
 * page colour with the button set inside it, on one row at every width
 * (MailPoet stacks them under 400px and sizes them itself, with !important
 * on the flex basis, hence the two here; its columns are size containers,
 * which would shrink the button column to nothing). Colours are palette tokens, so
 * the dark scheme and a Styles change follow. The button is Ghost's width
 * (its label plus 24px and a quarter em a side; 12px on phones) and the
 * placeholder is Ghost's fixed dark ink at 30% in BOTH schemes (on the
 * dark field it all but disappears, as on Ghost). Selector: the members
 * pattern's group, class ba-signup-form. */
.ba-signup-form .mailpoet_form .mailpoet_form_columns {
	flex-wrap: nowrap;
	align-items: center;
	box-sizing: border-box;
	height: 56px;
	padding: 0 5px 0 0;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
}

.ba-signup-form > .mailpoet_form {
	margin-block-start: 0;
}

.ba-signup-form .mailpoet_form .mailpoet_form_columns .mailpoet_form_column {
	container-type: normal;
	flex: 1 1 auto;
	flex-basis: auto !important;
	align-self: center;
	min-width: 0;
}

.ba-signup-form .mailpoet_form .mailpoet_form_columns .mailpoet_form_column:last-child {
	flex: 0 0 auto;
	margin-left: 8px !important;
}

.ba-signup-form .mailpoet_form .mailpoet_paragraph {
	margin: 0;
}

.ba-signup-form .mailpoet_form .mailpoet_text {
	height: 54px;
	margin: 0;
	padding: 1px 20px;
	border: 0;
	border-radius: 0;
	background: transparent;
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--body);
	font-size: 17px;
	font-weight: 450;
	line-height: 1;
	letter-spacing: -0.008em;
}

.ba-signup-form .mailpoet_form .mailpoet_text::placeholder {
	color: color-mix(in srgb, var(--wp--preset--color--ink) 30%, transparent);
	opacity: 1;
}

.ba-signup-form .mailpoet_form .mailpoet_text:focus {
	outline: 0;
}

.ba-signup-form .mailpoet_form .mailpoet_form_columns:focus-within {
	outline: 3px solid var(--wp--preset--color--focus);
	outline-offset: 2px;
}

.ba-signup-form .mailpoet_form .mailpoet_submit {
	width: auto !important;
	height: 44px;
	margin: 0;
	padding: 0 calc(24px + 0.25em);
	border: 0;
	border-radius: 0;
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	font-family: var(--wp--preset--font-family--body);
	font-size: 17px;
	font-weight: 600;
	line-height: 1;
	letter-spacing: -0.004em;
	cursor: pointer;
}

.ba-signup-form .mailpoet_form .mailpoet_submit:hover {
	background: var(--wp--preset--color--accent-ink);
	color: var(--wp--preset--color--on-accent-ink);
}

@media (max-width: 767px) {
	.ba-signup-form .mailpoet_form .mailpoet_submit {
		padding: 0 calc(12px + 0.25em);
		font-size: 16px;
	}
}

/* R9. Links under the greeting (betty.css 481-507): a centred Navigation
 * menu (patterns/hire-me-row.php, Group class ba-hire) whose links carry a
 * thick accent underline and darken on hover. Underline colour, offset and
 * thickness and the link hover colour have no block setting. accent-ink
 * turns into stage-accent in dark mode and inside a dark band (R1, R2), so
 * the row follows whatever it sits on. Since 2026-10-13 it is a plain menu
 * Betty edits in the Site Editor; the "Hire me:" label and the Hire site
 * role are gone. */
.ba-hire .wp-block-navigation-item__content {
	text-decoration: underline;
	text-decoration-color: var(--wp--preset--color--accent-ink);
	text-decoration-thickness: 2px;
	text-underline-offset: 4px;
}

.ba-hire .wp-block-navigation-item__content:hover,
.ba-hire .wp-block-navigation-item__content:focus {
	color: var(--wp--preset--color--contrast);
}

/* R10. Homepage portrait on phones (betty.css 509-517): 200px circle on
 * wide screens, 96px on phones, and 14px instead of 24px down to the
 * greeting (the hero's 18px block gap plus this margin). Featured image
 * width, height and margin are block attributes with no per-viewport
 * value. */
@media (max-width: 767px) {
	.ba-portrait.wp-block-post-featured-image,
	.ba-portrait.wp-block-post-featured-image img {
		width: 96px !important;
		height: 96px !important;
	}

	.ba-portrait.wp-block-post-featured-image {
		margin-bottom: -4px !important;
	}
}

/* RP. Content body (Post Content class
 * ba-page-body; Ghost page.hbs .gh-content, Source screen.css 2128-2320
 * and 2387-2497, betty.css 967-1034, Koenig cards.min.css). The page body
 * follows Ghost's card rhythm, which core's single block gap cannot say:
 * 56px before a heading, 12px from a heading to its paragraph, 48px around
 * quotes, separators and media/cards. Scoped to the
 * templates that give Post Content the class ba-page-body: page.html,
 * front-page.html and single.html (Ghost's page, home and post bodies are
 * the same .gh-content). The gallery template keeps its own rules.
 * A margin, colour or gap set on a block in the editor still wins (inline
 * styles and has-* classes). Colours are palette tokens only. */

/* RP1. Type: Ghost's content letter-spacing; h2/h3 at Playfair 550. */
.ba-page-body {
	letter-spacing: -0.01em;
}

.ba-page-body > h2 {
	letter-spacing: -0.02em;
}

.ba-page-body > h3 {
	letter-spacing: -0.017em;
}

.ba-page-body > :is(h2, h3) {
	font-weight: 550;
}

/* RP2. Rhythm. */
.ba-page-body > :is(h1, h2, h3, h4, h5, h6) + * {
	margin-block-start: 28px;
}

.ba-page-body > :is(h1, h2, h3, h4, h5, h6) + p {
	margin-block-start: 12px;
}

.ba-page-body > :is(h1, h2, h3, h4, h5, h6):not(:first-child) {
	margin-block-start: 56px;
}

/* An empty paragraph (a blank line, as Ghost keeps them around the older
 * Press items) holds its own margin like a child of Ghost's grid: 12px
 * after a heading or 28px after text, plus the margin of the block after
 * it. In normal flow its margins would collapse through it and the blank
 * line would vanish. */
.ba-page-body > p:empty {
	display: flow-root;
}

/* Ghost gives any anchored block (the review callouts) a heading's space
 * after a card; after text the card rule below (48px) wins. */
.ba-page-body > [id]:not(:first-child) {
	margin-block-start: 56px;
}

.ba-page-body > :not(:is(h1, h2, h3, h4, h5, h6, .wp-block-image, .wp-block-gallery, .wp-block-buttons, .wp-block-embed, .wp-block-group, .wp-block-video, .wp-block-audio, .wp-block-file, .wp-block-table, .wp-block-cover, .wp-block-columns, .wp-block-media-text, .wp-block-details)) + :is(.wp-block-image, .wp-block-gallery, .wp-block-buttons, .wp-block-embed, .wp-block-group, .wp-block-video, .wp-block-audio, .wp-block-file, .wp-block-table, .wp-block-cover, .wp-block-columns, .wp-block-media-text, .wp-block-details),
.ba-page-body > :is(.wp-block-image, .wp-block-gallery, .wp-block-buttons, .wp-block-embed, .wp-block-group, .wp-block-video, .wp-block-audio, .wp-block-file, .wp-block-table, .wp-block-cover, .wp-block-columns, .wp-block-media-text, .wp-block-details) + :not(:is(h1, h2, h3, h4, h5, h6, .wp-block-image, .wp-block-gallery, .wp-block-buttons, .wp-block-embed, .wp-block-group, .wp-block-video, .wp-block-audio, .wp-block-file, .wp-block-table, .wp-block-cover, .wp-block-columns, .wp-block-media-text, .wp-block-details)) {
	margin-block-start: 48px;
}

/* Quotes and separators take 48px both sides, even before a heading
 * (Ghost marks this !important; the doubled class outranks RP2's heading
 * rule instead). After a quote it is 60px: Ghost's .gh-content is a grid,
 * so the quote's own 12px bottom margin adds to the 48px instead of
 * collapsing (measured on Ghost: blockquote bottom 1860, next p 1920). */
.ba-page-body > :is(.wp-block-quote, .wp-block-pullquote, .wp-block-separator):not(:first-child),
.ba-page-body.ba-page-body > :is(.wp-block-pullquote, .wp-block-separator) + * {
	margin-block-start: 48px;
}

.ba-page-body.ba-page-body > .wp-block-quote + * {
	margin-block-start: 60px;
}

/* A Ghost quote breaks its paragraphs with a blank line, one quote line
 * high. */
.ba-page-body > .wp-block-quote > p + p {
	margin-block-start: 1.3em;
}

/* RP3. Lists (Source: 28px indent, 8px between items). */
.ba-page-body :is(ul, ol).wp-block-list {
	padding-left: 28px;
}

.ba-page-body :is(li + li, li > ul, li > ol) {
	margin-top: 8px;
}

/* RP4. Pictures: a picture narrower than the measure sits centred, and a
 * picture, gallery or embed caption is centred under it in the text
 * colour (Source figcaption). Per-work captions inside a gallery are R11. */
.ba-page-body > .wp-block-image:not(.alignleft, .alignright) img {
	display: block;
	margin-inline: auto;
}

.ba-page-body > :is(.wp-block-image, .wp-block-embed, .wp-block-video) > figcaption,
.ba-page-body > .wp-block-gallery > figcaption.blocks-gallery-caption {
	margin: 12px 0 0;
	color: var(--wp--preset--color--contrast);
	font-size: 14px;
	line-height: 1.6;
	text-align: center;
}

/* The gallery caption wraps to its own flex line, so the row gap is
 * already above it. */
.ba-page-body > .wp-block-gallery > figcaption.blocks-gallery-caption {
	margin-top: max(0px, 12px - var(--wp--style--unstable-gallery-gap, 16px));
}

/* RP5. Galleries with the default column setting lay out like Ghost's
 * gallery card: rows of three at every width (phones too), a last row of
 * one split into two pairs, 12px gaps (6px under 600px). Counted by type,
 * because a gallery caption is a sibling of the pictures. Columns, gap or
 * a block style chosen on the gallery take over, except Greyscale (R7a),
 * which keeps these rows. */
.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale):not([class*="wp-container-core-gallery"]) {
	--wp--style--unstable-gallery-gap: 12px;
	gap: 12px;
}

.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale) figure.wp-block-image:not(#individual-image) {
	width: calc(33.33% - var(--wp--style--unstable-gallery-gap, 16px) * 0.66667);
}

.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale) figure.wp-block-image:not(#individual-image):first-of-type:nth-last-of-type(2),
.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale) figure.wp-block-image:not(#individual-image):first-of-type:nth-last-of-type(2) ~ figure.wp-block-image:not(#individual-image),
.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale) figure.wp-block-image:not(#individual-image):nth-of-type(3n+1):nth-last-of-type(4),
.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale) figure.wp-block-image:not(#individual-image):nth-of-type(3n+2):nth-last-of-type(3),
.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale) figure.wp-block-image:not(#individual-image):nth-of-type(3n+3):nth-last-of-type(2),
.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale) figure.wp-block-image:not(#individual-image):nth-of-type(3n+4):nth-last-of-type(1) {
	width: calc(50% - var(--wp--style--unstable-gallery-gap, 16px) * 0.5);
}

.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale) figure.wp-block-image:not(#individual-image):only-of-type {
	width: 100%;
}

/* Ghost draws each picture across its whole cell (Koenig's gallery image
 * has no object-fit): a row is as tall as its tallest picture and the
 * others stretch to it, nothing is cropped (the 2x2 press badges). Rows
 * of equal cells do this from four pictures up. A gallery of one row
 * (three pictures or fewer) whose pictures carry their proportions as
 * --ba-ratio (width / height, printed on each picture by the ba-site
 * mu-plugin) sizes each cell by it as Koenig does (flex: <ratio> 1 0%),
 * so every picture is whole at one height; without --ba-ratio it keeps
 * the equal cells above and core's crop. */
.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale):has(> figure.wp-block-image:nth-of-type(4)) figure.wp-block-image:not(#individual-image) img,
.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale):not(:has(> figure.wp-block-image:nth-of-type(4))) figure.wp-block-image:not(#individual-image)[style*="--ba-ratio"] img {
	object-fit: fill;
}

.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale):not(:has(> figure.wp-block-image:nth-of-type(4))) figure.wp-block-image:not(#individual-image)[style*="--ba-ratio"] {
	flex: var(--ba-ratio) 1 0%;
	width: auto;
	min-width: 0;
}

@media (max-width: 599px) {
	.ba-page-body .wp-block-gallery.has-nested-images.columns-default:is(:not([class*="is-style-"]), .is-style-greyscale):not([class*="wp-container-core-gallery"]) {
		--wp--style--unstable-gallery-gap: 6px;
		gap: 6px;
	}
}

/* RP6. Buttons: a body button is the accent button (Ghost's button card
 * default, kg-btn-accent) unless Betty picks colours or the Outline
 * style; type and padding as the card (Source 2389-2395). The colours are
 * the button / on-button tokens, which R1 does not remap: #b000b8 with
 * white text in both schemes, as Ghost. */
.ba-page-body .wp-block-button:not(.is-style-outline) > .wp-block-button__link:not(.has-background) {
	background-color: var(--wp--preset--color--button);
}

.ba-page-body .wp-block-button:not(.is-style-outline) > .wp-block-button__link:not(.has-text-color) {
	color: var(--wp--preset--color--on-button);
}

.ba-page-body .wp-block-button:not(.is-style-outline) > .wp-block-button__link:not(.has-border-color) {
	border-width: 0;
}

.ba-page-body .wp-block-button > .wp-block-button__link:not(.has-custom-font-size) {
	padding: 0.6em 1.2em;
	font-size: 18px;
	line-height: 1.2;
	transition: opacity 0.2s ease-in-out;
}

.ba-page-body .wp-block-button:not(.is-style-outline) > .wp-block-button__link:hover {
	opacity: 0.85;
}

/* RP7. Callouts: the import's review-item notes (a Group with the dark
 * band style and no background of its own, Ghost callout card) are a
 * surface box at 0.95em in the page's own colours: the stage remap of R2
 * steps back to the inherited palette (inherit), so nothing is
 * hard-coded and dark mode still follows R1. The text colour is set back
 * to the page's own too, over the Dark band style's stage text from
 * theme.json. One rule for content pages and gallery pages; R11b adds
 * what the gallery body needs. */
:is(.ba-page-body, .ba-gallery-body) > .wp-block-group.is-style-dark-band:not(.has-background) {
	--wp--preset--color--base: inherit;
	--wp--preset--color--surface: inherit;
	--wp--preset--color--contrast: inherit;
	--wp--preset--color--muted: inherit;
	--wp--preset--color--line: inherit;
	--wp--preset--color--accent-ink: inherit;
	--wp--preset--color--on-accent-ink: inherit;
	padding: 1.2em 1.6em;
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--contrast);
}

:is(.ba-page-body, .ba-gallery-body) > .wp-block-group.is-style-dark-band:not(.has-background) > * {
	font-size: 0.95em;
	line-height: 1.5;
}

:is(.ba-page-body, .ba-gallery-body) > .wp-block-group.is-style-dark-band:not(.has-background) > * + * {
	margin-block-start: 1em;
}

/* R11. Gallery captions under the work (betty.css 1177-1191). Core lays a
 * Gallery caption over the bottom of the image on a dark gradient; Ghost
 * prints it under the frame, muted, with the BOLD words on their own line
 * in the heading face (title, then medium and size). Core's selectors carry
 * the Gallery's own weight, which the :where()-wrapped custom CSS of
 * theme.json cannot outrank, so this is here. */
.wp-block-gallery.has-nested-images figure.wp-block-image:has(figcaption) {
	flex-direction: column;
	justify-content: flex-start;
}

.wp-block-gallery.has-nested-images figure.wp-block-image:has(figcaption)::before {
	content: none;
}

.wp-block-gallery.has-nested-images figure.wp-block-image figcaption {
	position: static;
	flex: none;
	width: 100%;
	max-height: none;
	overflow: visible;
	margin: 22px 0 0;
	padding: 0;
	background: none;
	color: var(--wp--preset--color--muted);
	font-size: 14px;
	line-height: 1.45;
	text-align: left;
	text-shadow: none;
}

.wp-block-gallery.has-nested-images figure.wp-block-image figcaption strong,
.wp-block-gallery.has-nested-images figure.wp-block-image figcaption b {
	display: block;
	font-family: var(--wp--preset--font-family--heading);
	font-size: 20px;
	font-weight: 400;
	line-height: 1.25;
	color: var(--wp--preset--color--contrast);
}

/* R11a. Gallery page body (betty.css 1198-1201, .ba-gallery > p): a note
 * between the works keeps the reading measure, starts at the left edge of
 * the grid and is muted. Paragraph has no width setting, and the Post
 * Content layout centres every child. 1320px is the Post Content content
 * size of templates/page-gallery.html (class ba-gallery-body). A colour
 * chosen on the paragraph (has-*-color) still wins. */
.ba-gallery-body > p {
	max-width: var(--wp--style--global--content-size);
	margin-left: max(0px, (100% - 1320px) / 2) !important;
	color: var(--wp--preset--color--muted);
}

/* R11b. Gallery page type and callouts (Ghost .gh-content letter-spacing;
 * betty.css 1020-1023 callout card on --surface; Source callout text
 * 0.95em / 1.5, padding 1.2em 1.6em). The gallery body tracks at -0.01em
 * like every Ghost content body (captions included). A review-item callout
 * (the import's dark-band Group with no background of its own) is a
 * surface box (RP7) across the full grid width with its text
 * unconstrained inside it: the gallery body's Post Content is constrained
 * at 1320px, so without the reset below the text would centre at 680px.
 * Ghost adds its card-to-text 48px to the 32px grid gap, so text after a
 * callout starts 80px below it; a gallery straight after keeps the grid
 * gap alone. */
.ba-gallery-body {
	letter-spacing: -0.01em;
}

.ba-gallery-body > .wp-block-group.is-style-dark-band:not(.has-background) > * {
	max-width: none;
	margin-left: 0 !important;
	margin-right: 0 !important;
}

.ba-gallery-body > .wp-block-group.is-style-dark-band:not(.has-background) + :not(.wp-block-gallery, .wp-block-image) {
	margin-block-start: 80px;
}

/* Under 600px Ghost's gallery grid gap is 28px (betty.css 1209-1213):
 * 28px between body blocks, 76px from a callout to the text after it. */
@media (max-width: 599px) {
	.ba-gallery-body.ba-gallery-body > * + * {
		margin-block-start: 28px;
	}

	.ba-gallery-body.ba-gallery-body > .wp-block-group.is-style-dark-band:not(.has-background) + :not(.wp-block-gallery, .wp-block-image) {
		margin-block-start: 76px;
	}
}

/* R11c. Lightbox (Source lightbox.js + partials/lightbox.hbs: PhotoSwipe 4
 * with bgOpacity 0.9 over .pswp__bg rgba(0,0,0,.85), barsSize 44px).
 * Ghost shows each work WHOLE, fitted between a 44px top bar and a 44px
 * bottom margin across the full width, never past its own size, on a dark
 * scrim, with a "1 / 26" counter at the top left, a close X at the top
 * right and arrows at mid height. Core's "Enlarge on click" overlay sizes
 * its box from the thumbnail's rendered 4:3 frame (so a portrait work in an
 * Uncropped or Cover gallery is cropped to landscape) and paints the scrim
 * in the page background colour. The overlay is one element for the whole
 * page, so this applies to every lightbox, as PhotoSwipe does in Ghost.
 * The box is the viewport less the bars and the picture is sized by its
 * own proportions inside it; core's zoom from the thumbnail assumes core's
 * box, so the picture fades in and out instead (PhotoSwipe's 333ms). The
 * thumbnail stays on the page under the scrim, as in Ghost. */
.wp-lightbox-overlay .lightbox-image-container {
	top: 44px;
	left: 0;
	width: 100%;
	height: calc(100% - 88px);
	transform: none;
}

.wp-lightbox-overlay .lightbox-image-container .wp-block-image img {
	width: auto;
	height: auto;
	min-width: 0;
	min-height: 0;
	max-width: 100%;
	max-height: 100%;
}

/* Core stacks two copies: the thumbnail as the page loaded it, then the
 * enlarged copy with sizes="100vw", whose srcset makes the browser treat
 * it as viewport-wide whatever its real size. The thumbnail copy has its
 * real size, so it sets the box and the enlarged copy is drawn over it at
 * exactly that size (anchor positioning; a browser without it shows the
 * enlarged copy fitted to the same bars). */
@supports (anchor-name: --a) {
	.wp-lightbox-overlay .lightbox-image-container:has(+ .lightbox-image-container) .wp-block-image img {
		anchor-name: --ba-lightbox-work;
	}

	.wp-lightbox-overlay .lightbox-image-container + .lightbox-image-container {
		position-anchor: --ba-lightbox-work;
		top: anchor(top);
		left: anchor(left);
		width: anchor-size(width);
		height: anchor-size(height);
	}

	.wp-lightbox-overlay .lightbox-image-container + .lightbox-image-container .wp-block-image img {
		width: 100%;
		height: 100%;
		max-width: none;
		max-height: none;
	}
}

.wp-lightbox-overlay.zoom.active .lightbox-image-container {
	animation: turn-on-visibility 333ms both;
}

.wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container {
	animation: turn-off-visibility 333ms both;
}

.wp-lightbox-container img.hide {
	visibility: visible;
}

/* Core gives the "Enlarge" trigger backdrop-filter: blur(16px)
 * saturate(180%) (image/style.min.css) even while it is invisible
 * (opacity 0). In Chromium any backdrop-filter layer drops the whole page's
 * text from LCD to greyscale antialiasing, unlike Ghost, which has no such
 * button. The button keeps core's translucent background. Specificity
 * (0,2,1) beats core's (0,1,1); theme.json block css would compile to
 * (0,1,0) and lose. */
.wp-lightbox-container button.lightbox-trigger {
	backdrop-filter: none;
}

/* The scrim: core prints the page background as an inline style and fades
 * it to full opacity, so the colour carries Ghost's alpha (0.85 x 0.9). */
.wp-lightbox-overlay .scrim {
	background-color: var(--wp--custom--lightbox--scrim, color-mix(in srgb, var(--wp--preset--color--stage-bg) 76.5%, transparent)) !important;
}

/* Close and arrows: PhotoSwipe's default skin glyphs (default-skin.svg),
 * drawn through a mask in the lightbox UI colour. Core's own icons are
 * inline SVGs filled with the text colour, which vanish on the dark scrim.
 * Close: a 44px square in the corner. Arrows: 70 x 100 at mid height on
 * the edges, the glyph 15px in and 44px down. PhotoSwipe keeps the arrows
 * off touch screens (swipe instead); so does this. */
.wp-lightbox-overlay .wp-lightbox-close-button.wp-lightbox-close-button,
.wp-lightbox-overlay .wp-lightbox-navigation-button.wp-lightbox-navigation-button {
	box-sizing: border-box;
	padding: 0;
	min-width: 0;
	min-height: 0;
	transform: none;
}

.wp-lightbox-overlay .wp-lightbox-close-button.wp-lightbox-close-button {
	top: 0;
	right: 0;
	width: 44px;
	height: 44px;
}

.wp-lightbox-overlay .wp-lightbox-navigation-button.wp-lightbox-navigation-button {
	top: 50%;
	bottom: auto;
	width: 70px;
	height: 100px;
	margin-top: -50px;
}

.wp-lightbox-overlay .wp-lightbox-navigation-button-prev.wp-lightbox-navigation-button-prev {
	left: 0;
}

.wp-lightbox-overlay .wp-lightbox-navigation-button-next.wp-lightbox-navigation-button-next {
	right: 0;
}

.wp-lightbox-overlay :is(.wp-lightbox-close-icon, .wp-lightbox-navigation-icon) svg {
	display: none;
}

.wp-lightbox-overlay :is(.wp-lightbox-close-button, .wp-lightbox-navigation-button)::before {
	content: "";
	position: absolute;
	background-color: var(--wp--custom--lightbox--ui, var(--wp--preset--color--stage-text));
}

.wp-lightbox-overlay .wp-lightbox-close-button::before {
	top: 0;
	left: 0;
	width: 44px;
	height: 44px;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 44 44 44'%3E%3Cpath d='M20.586 66l-5.656-5.656 1.414-1.414L22 64.586l5.656-5.656 1.414 1.414L23.414 66l5.656 5.656-1.414 1.414L22 67.414l-5.656 5.656-1.414-1.414L20.586 66z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 44 44 44'%3E%3Cpath d='M20.586 66l-5.656-5.656 1.414-1.414L22 64.586l5.656-5.656 1.414 1.414L23.414 66l5.656 5.656-1.414 1.414L22 67.414l-5.656 5.656-1.414-1.414L20.586 66z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}

.wp-lightbox-overlay .wp-lightbox-navigation-button::before {
	top: 35px;
	width: 32px;
	height: 30px;
}

.wp-lightbox-overlay .wp-lightbox-navigation-button-prev::before {
	left: 6px;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='138 44 32 30'%3E%3Cpath d='M152.215 65.03L154 63.5l-3-3.5h10v-2h-10l3-3.5-1.785-1.468L147 59l5.215 6.03z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='138 44 32 30'%3E%3Cpath d='M152.215 65.03L154 63.5l-3-3.5h10v-2h-10l3-3.5-1.785-1.468L147 59l5.215 6.03z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}

.wp-lightbox-overlay .wp-lightbox-navigation-button-next::before {
	right: 6px;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='94 44 32 30'%3E%3Cpath d='M111.785 65.03L110 63.5l3-3.5h-10v-2h10l-3-3.5 1.785-1.468L117 59l-5.215 6.03z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='94 44 32 30'%3E%3Cpath d='M111.785 65.03L110 63.5l3-3.5h-10v-2h10l-3-3.5 1.785-1.468L117 59l-5.215 6.03z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}

@media (hover: none) and (pointer: coarse) {
	.wp-lightbox-overlay .wp-lightbox-navigation-button.wp-lightbox-navigation-button {
		display: none;
	}
}

/* The counter ("2 / 19", Figtree 11px bold on a 44px line, 15px in) is
 * worked out with CSS counters, as the overlay carries no position: core
 * marks the open work's thumbnail img.hide, so in that gallery every work
 * counts towards the total and the works up to and including the open one
 * towards the position. The body resets both, so the overlay (printed at
 * the end of the body) reads them. Hidden when the open work is not in a
 * gallery or is the gallery's only work (PhotoSwipe's one-slide rule),
 * and when the overlay already carries a counter element of its own
 * (.ba-lightbox-counter, the ba-site mu-plugin's lightbox.php). */
body {
	counter-reset: ba-lightbox-index ba-lightbox-total;
}

.wp-block-gallery:has(> figure.wp-lightbox-container img.hide) > figure.wp-lightbox-container {
	counter-increment: ba-lightbox-total;
}

.wp-block-gallery:has(> figure.wp-lightbox-container img.hide) > figure.wp-lightbox-container:is(:has(img.hide), :has(~ figure.wp-lightbox-container img.hide)) {
	counter-increment: ba-lightbox-index ba-lightbox-total;
}

body:has(.wp-block-gallery > figure.wp-lightbox-container:not(:only-of-type) img.hide) .wp-lightbox-overlay.active:not(:has(.ba-lightbox-counter))::after {
	content: counter(ba-lightbox-index) " / " counter(ba-lightbox-total);
	position: absolute;
	top: 0;
	left: 0;
	z-index: 5000000;
	height: 44px;
	padding: 0 15px;
	color: var(--wp--custom--lightbox--ui, var(--wp--preset--color--stage-text));
	font-family: var(--wp--preset--font-family--body);
	font-size: 11px;
	font-weight: 700;
	line-height: 44px;
	letter-spacing: normal;
	user-select: none;
}

/* R12. Writing feed cards (betty.css 1272-1290; Source screen.css
 * .gh-card-title text-wrap, .gh-card-excerpt line clamp). The /writing/
 * feed (templates/home.html, class hooks ba-feed-featured and ba-feed) and
 * the archive fallback (templates/index.html, ba-feed) clamp the excerpt to
 * two lines with an ellipsis and balance the card titles. The Post Excerpt
 * block has a word count but no line clamp, and theme.json has no
 * text-wrap or line-clamp property. No colour here. */
.ba-feed .wp-block-post-title,
.ba-feed-featured .wp-block-post-title {
	text-wrap: pretty;
}

.ba-feed .wp-block-post-excerpt__excerpt,
.ba-feed-featured .wp-block-post-excerpt__excerpt {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
}

/* R13. Post Share button (Ghost post.hbs .gh-button-share, betty.css
 * 1365-1369). templates/single.html puts a Details block (class
 * ba-share-toggle) in the byline: its summary "Share" is the outline
 * button (border, padding, type and colour are block settings), and
 * opening it drops the share links (ba-share-links, hrefs set at render
 * time by the members mu-plugin) below it without moving the page. Core
 * has no setting for the disclosure marker or an overlaid panel. The
 * border colour is set here (the palette slug is "line" since round 1, so
 * a block border colour no longer collides with a text colour class).
 * Colours are palette tokens only. */
.ba-share-toggle {
	position: relative;
	flex-shrink: 0;
	border-color: var(--wp--preset--color--line);
}

.ba-share-toggle > summary {
	list-style: none;
	cursor: pointer;
}

.ba-share-toggle > summary::-webkit-details-marker {
	display: none;
}

.ba-share-toggle > .ba-share-links {
	position: absolute;
	top: calc(100% + 6px);
	right: -1px;
	z-index: 10;
	margin: 0;
	padding: 12px 14px;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
}

.ba-share-toggle .ba-share-links .wp-social-link {
	color: currentColor;
}

/* R14. Comments call to action for signed-out readers (Ghost post.hbs
 * comments CTA; markup from the members mu-plugin, classes
 * ba-comments-cta, ba-comments-cta__signup, ba-comments-cta__signin,
 * contract "Members"). The button is the body button (button / on-button,
 * as RP6); the heading is Ghost's sans "Start the conversation". Ghost's
 * comments-ui is a system sans, not the theme font: single.html sets that
 * stack on the comments group, and the heading and button inherit it. */
.ba-comments-cta .wp-element-button {
	padding: 14px 20px;
	font-family: inherit;
	border-width: 0;
	background-color: var(--wp--preset--color--button);
	color: var(--wp--preset--color--on-button);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
}

.ba-comments-cta .wp-element-button:hover {
	background-color: var(--wp--preset--color--button);
	color: var(--wp--preset--color--on-button);
	opacity: 0.85;
}

.wp-block-post-comments-form #reply-title.comment-reply-title,
.ba-comments-cta + #reply-title.comment-reply-title {
	font-family: inherit;
	font-size: 24px;
	font-weight: 600;
	line-height: 1.5;
	letter-spacing: -0.018em;
	margin-top: 0;
}

/* Ghost's comments-ui rhythm: the invitation 8px under the heading, the
 * button 28px under it, the sign-in line 12px under the button. */
.ba-comments-cta p {
	margin: 0;
}

.ba-comments-cta .must-log-in {
	margin-top: 8px;
	color: var(--wp--preset--color--muted);
	font-size: 16.5px;
	line-height: 1.5;
}

.ba-comments-cta .must-log-in strong {
	font-weight: 600;
}

.ba-comments-cta .ba-comments-cta__signup {
	display: flex;
	justify-content: center;
	margin-top: 28px;
}

.ba-comments-cta .ba-comments-cta__signin {
	margin-top: 12px;
}

/* "Already a member?" is Ghost's 15px line at 40% of the text colour
 * (comments-ui text-black/40), the Sign in link 14px 600. The colour is
 * mixed from the contrast token, so it follows the dark scheme and a
 * Styles edit. */
.ba-comments-cta__signin {
	color: color-mix(in srgb, var(--wp--preset--color--contrast) 40%, transparent);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
}

.ba-comments-cta__signin a {
	color: var(--wp--preset--color--accent-ink);
	font-size: 14px;
	font-weight: 600;
	text-decoration: none;
}

/* The comment count beside "Member discussion" (single.html Post Comments
 * Link, class ba-comments-count) is Ghost's comments-ui count at 50% of the
 * text colour (text-neutral-900/50), mixed from the contrast token as the
 * sign-in line above. Core's style engine drops color-mix() from block
 * attributes, so it lives here, with the link's no-underline (an elements
 * link style without a colour prints no CSS). */
.ba-comments-count,
.ba-comments-count a {
	color: color-mix(in srgb, var(--wp--preset--color--contrast) 50%, transparent);
}

.ba-comments-count a {
	text-decoration: none;
}

/* R15. Post title (Ghost .gh-article-title, betty.css 1336-1339): the
 * single template's Post Title (class ba-article-title) wraps "pretty", so
 * a phone title breaks where Ghost's does. theme.json has no text-wrap
 * property. No colour here. */
.ba-article-title {
	text-wrap: pretty;
}

/* R16. Home hero intro (betty.css .ba-home-intro): the front-page Post
 * Excerpt in the hero group (the group holding the .ba-portrait featured
 * image) wraps "pretty". Was the hero group's block Additional CSS until
 * Betty test D1: DISALLOW_UNFILTERED_HTML strips block CSS from any
 * template the Site Editor saves, so no template, part or pattern carries
 * a block "css" attribute (scripts/lint.sh). */
.wp-block-group:has(> .ba-portrait) .wp-block-post-excerpt {
	text-wrap: pretty;
}

/* R17. Title band (patterns/title-band.php, Ghost page.hbs
 * .ba-page-header; Columns inside the dark band): a page with no featured
 * image gets one full-width column (the empty image Column hides), title
 * and standfirst wrap "pretty", and a copy Column with a standfirst but no
 * Post Terms keeps the 14px of Ghost's empty kicker row above the title
 * (Ghost's {{#if tags}} is true for internal tags). Was the Columns block's
 * Additional CSS until D1 (see R16). */
.is-style-dark-band > .wp-block-columns > .wp-block-column:empty {
	display: none;
}

.is-style-dark-band > .wp-block-columns .wp-block-post-title,
.is-style-dark-band > .wp-block-columns .wp-block-post-excerpt {
	text-wrap: pretty;
}

.is-style-dark-band > .wp-block-columns > .wp-block-column:not(:has(.wp-block-post-terms)):has(.wp-block-post-excerpt) {
	padding-top: 14px;
}

/* R18. Phone menu (parts/navigation-overlay.html, Group ba-menu-overlay):
 * the overlay is one screen tall and the dark card fills what the header
 * row and the Subscribe / Sign in foot leave, scrolling inside itself.
 * Height, min-height and overflow have no block setting. Was the group's
 * Additional CSS until D1 (see R16). */
.wp-block-group.ba-menu-overlay {
	height: 100vh;
	height: 100dvh;
}

.wp-block-group.ba-menu-overlay > .ba-menu-card {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	overscroll-behavior: contain;
}
