/*
Theme Name: PasteTheme
Theme URI: https://pastetheme.com
Author: Chattanooga Tshirt
Author URI: https://pastetheme.com/about/
Description: A real business website: a phone-first block theme with one typeface, light and dark colors, pill buttons and curved gel details. A static front page and a handful of pages, not a blog theme. PasteTheme is free. If it saved you a day, buy us a coffee: ko-fi.com/chattanoogatshirt
Version: 0.9.0
Requires at least: 7.1
Tested up to: 7.1
Requires PHP: 8.0
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: pastetheme
Update URI: https://pastetheme.com/paste/
Tags: full-site-editing, one-column, wide-blocks, custom-colors, custom-logo, editor-style, block-patterns, style-variations
*/

/* ---- Font fallback ------------------------------------------------------------------
   Text paints at once in a fallback font and changes to Quicksand when its file lands (font-display:
   swap). A plain system font is a different width, so lines wrapped differently when Quicksand arrived
   and the page jumped (pastetheme.com /features/, 0.162 on a slow phone, 26 Sep 2026). These faces are
   system fonts resized to Quicksand's width and line box, one per weight the theme uses, so the swap
   barely moves a line. Measured in Chrome on a sample site's own text: Quicksand is 102.18% of
   Arial's width at 300 and 104.06% at 400, and 85.98% of Verdana Bold's at 700. Bold is Verdana because
   headings are often capped in ch (the width of a "0"): resized Arial Bold's "0" came out 7.5% narrower
   than Quicksand's and a capped heading gained a line, Verdana Bold's is within 0.5%. On 20 pages at
   390 and 1280 wide, 28 text blocks changed height when the font landed, against 221 with the old
   system stack. Ascent 1 and descent 0.25 of the size, as Quicksand's, divided by size-adjust because
   the browser scales the overrides by it. Arial and Verdana ship with Windows, macOS and iOS; where one
   is missing its face is skipped and the rest of the stack in theme.json takes over. functions.php also
   preloads the latin file while Quicksand is in use. */
@font-face {
	font-family: 'Quicksand Fallback';
	font-weight: 300;
	src: local('Arial'), local('ArialMT');
	size-adjust: 102.18%;
	ascent-override: 97.87%;
	descent-override: 24.47%;
	line-gap-override: 0%;
}
@font-face {
	font-family: 'Quicksand Fallback';
	font-weight: 400;
	src: local('Arial'), local('ArialMT');
	size-adjust: 104.06%;
	ascent-override: 96.1%;
	descent-override: 24.02%;
	line-gap-override: 0%;
}
@font-face {
	font-family: 'Quicksand Fallback';
	font-weight: 700;
	src: local('Verdana Bold'), local('Verdana-Bold');
	size-adjust: 85.98%;
	ascent-override: 116.31%;
	descent-override: 29.08%;
	line-gap-override: 0%;
}
/* Android ships neither Arial nor Verdana, so the faces above are skipped there and phones painted in
   plain Roboto, then rewrapped when Quicksand landed. The same three weights from Android's own Roboto,
   measured the same way on pastetheme.com's text (3 Oct 2026): Quicksand is 104.02%, 104.13% and 107.80%
   of Roboto's width, and Roboto Bold's "0" is within 0.8% of Quicksand's after the adjust. theme.json
   lists this family after the first, so a device with Arial never reaches it. */
@font-face {
	font-family: 'Quicksand Fallback Roboto';
	font-weight: 300;
	src: local('Roboto Light'), local('Roboto-Light'), local('Roboto');
	size-adjust: 104.02%;
	ascent-override: 96.14%;
	descent-override: 24.03%;
	line-gap-override: 0%;
}
@font-face {
	font-family: 'Quicksand Fallback Roboto';
	font-weight: 400;
	src: local('Roboto'), local('Roboto Regular'), local('Roboto-Regular');
	size-adjust: 104.13%;
	ascent-override: 96.04%;
	descent-override: 24.01%;
	line-gap-override: 0%;
}
@font-face {
	font-family: 'Quicksand Fallback Roboto';
	font-weight: 700;
	src: local('Roboto Bold'), local('Roboto-Bold'), local('Roboto');
	size-adjust: 107.8%;
	ascent-override: 92.76%;
	descent-override: 23.19%;
	line-gap-override: 0%;
}

/* Theme styles live in a cascade layer so pasted sections and plugins
   always win specificity fights without !important. */
@layer pastetheme {
	body {
		margin: 0;
		-webkit-font-smoothing: antialiased;
	}
	img {
		max-width: 100%;
		height: auto;
	}
	/* A long unbroken word (an address, a file path, an email) breaks onto the next line instead of
	   running to the screen edge on a phone (phone audit #13, 26 Sep 2026). break-word, not anywhere:
	   it only breaks a word that would overflow, so nothing else in a section changes width. Layered,
	   so a section's own wrapping wins. */
	.pt-section {
		position: relative;
		overflow-wrap: break-word;
	}
	/* Sections own their layout edge-to-edge. Every descendant sizes as a border box: CSS an
	   AI writes assumes a global border-box reset, and the pipeline scopes that reset away, so a
	   button with a minimum height, or a card with width 100% and padding, computed content-box
	   and grew or overflowed (five sample buttons were patched by hand before this). Layered,
	   so a section's own box-sizing still wins. */
	.pt-section,
	.pt-section * {
		box-sizing: border-box;
	}

	/* The first element in a section's content box adds no top margin: the browser gives an h1
	   0.67em (40px at 1280) that stacked on the section's own padding above every AI hero
	   (14 Sep 2026). Layered, so any spacing a section brings still wins. */
	.pt-section .pt-wrap > :first-child {
		margin-block-start: 0;
	}
	/* The same at the bottom: a section that ended with a paragraph or a list added its browser margin
	   to its own padding, so the gap under it came out one margin wider than the gap under a section that
	   ended with a box (93, 113 and 133px on one page, phone audit, 26 Sep 2026). */
	.pt-section .pt-wrap > :last-child {
		margin-block-end: 0;
	}

	/* Form baseline: an UNstyled pasted form still looks finished. Layered,
	   so any CSS that arrives with a pasted section wins without effort.
	   The button-like input types are excluded from the text-control rule: it carries three
	   :not()s and so outranked `.pt-section input[type='submit']` at equal layer, and a pasted
	   form's submit button rendered as a white full-width text field (21 Sep 2026). A file input
	   stays a text control on purpose: a file-upload field wants the same box. */
	.pt-section label {
		display: block;
		font-weight: 600;
		margin-block: 0 1rem;
	}
	:is(.pt-section, .pt-pasted-form) input:not([type='checkbox']):not([type='radio']):not([type='hidden']):not([type='submit']):not([type='button']):not([type='reset']):not([type='image']),
	.wp-block-html form input:not([type='checkbox']):not([type='radio']):not([type='hidden']):not([type='submit']):not([type='button']):not([type='reset']):not([type='image']),
	:is(.pt-section, .pt-pasted-form) select,
	.wp-block-html form select,
	:is(.pt-section, .pt-pasted-form) textarea,
	.wp-block-html form textarea {
		display: block;
		width: 100%;
		max-width: 32rem;
		box-sizing: border-box;
		font: inherit;
		padding: 0.6em 0.8em;
		margin-block: 0.3em 0;
		/* The field paints itself base, so its text and edge ride contrast, not the section's
		   color: a form on a dark band inherited white text onto a white field, and an edge at
		   30% of the text color was 2.0:1 against the page (WCAG 1.4.11 asks 3:1 for a control's
		   boundary). 50% of contrast is 3.5:1 light, 5.3:1 dark. */
		border: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast, #121212) 50%, transparent);
		border-radius: var(--pt-radius-l, 1rem);
		background: var(--wp--preset--color--base, #fff);
		color: var(--wp--preset--color--contrast, #121212);
	}
	:is(.pt-section, .pt-pasted-form) input[type='checkbox'],
	.wp-block-html form input[type='checkbox'],
	:is(.pt-section, .pt-pasted-form) input[type='radio'],
	.wp-block-html form input[type='radio'] {
		width: auto;
		display: inline-block;
		margin-inline-end: 0.4em;
	}
	:is(.pt-section, .pt-pasted-form) button,
	.wp-block-html form button,
	:is(.pt-section, .pt-pasted-form) input[type='submit'],
	.wp-block-html form input[type='submit'] {
		font: inherit;
		font-weight: 700;
		padding: 0.7em 1.6em;
		border: 0;
		border-radius: var(--pt-radius-s, 999px);
		background: var(--wp--preset--color--accent, #0000ff);
		color: var(--wp--preset--color--accent-contrast, #fff);
		cursor: pointer;
	}
	.pt-form-success,
	.pt-form-error {
		max-width: 32rem;
	}
	/* The same finished look for a form pasted with the theme alone (13 Oct 2026): a <form> in WordPress's own
	   Custom HTML block gets pt-pasted-form from inc/pasted.php, and the controls above take it as they take a
	   section's. Before, the baseline reached only the plugin's sections, and a pasted form was the browser's own:
	   13px boxes on one line and a grey Send. Its labels sit over their fields whether they wrap the field or stand
	   before it (the room is above the label, so a field never touches the next label), and Send keeps a line's
	   room above it. A form the theme cannot send (pt-form-unsent: no plugin to send it) has its Send switched off
	   and says so in one line under it, the note inc/pasted.php prints; the block editor shows the same note
	   (assets/editor.js). The block editor draws a Custom HTML block's HTML in the page itself, inside
	   .wp-block-html with no class of ours on the form, so the same rules name that too and the editor shows the
	   form as the page will. Layered like the rest, so a form's own CSS wins. */
	:is(.pt-pasted-form, .wp-block-html form) label {
		display: block;
		font-weight: 600;
		margin-block: 1rem 0;
	}
	:is(.pt-pasted-form, .wp-block-html form) > label:first-child {
		margin-block-start: 0;
	}
	:is(.pt-pasted-form, .wp-block-html form) :is(button, input[type='submit']) {
		margin-block-start: 1.25rem;
	}
	.pt-form-unsent :is(button, input[type='submit'])[disabled] {
		opacity: 0.55;
		cursor: not-allowed;
	}
	.pt-form-note {
		font-size: 0.9em;
		margin-block: 0.75rem 0;
	}

	/* ---- Phone hygiene ----------------------------------------------------
	   A pasted section wider than the screen must not scroll the whole page
	   sideways. `clip` on the root (not `hidden`, and never on body) reaches the
	   viewport without making a scroll container, so the floating header's
	   position: sticky keeps working. Video and embeds shrink like images do. */
	html {
		overflow-x: clip;
	}
	video {
		max-width: 100%;
		height: auto;
	}
	iframe {
		max-width: 100%;
	}
	/* Core's menu buttons (open and close) are drawn at 24px. They show only when the menu folds under
	   one button, on a phone and also on a short window used with a mouse (Short screens, below), so
	   the invisible, centered 44px tap area goes on wherever they are drawn: the button keeps its look and
	   the pad clicks through to it. The close button is already positioned by core. */
	.wp-block-navigation__responsive-container-open {
		position: relative;
	}
	.wp-block-navigation__responsive-container-open::before,
	.wp-block-navigation__responsive-container-close::before {
		content: '';
		position: absolute;
		top: 50%;
		left: 50%;
		width: max(44px, 100%);
		height: max(44px, 100%);
		translate: -50% -50%;
	}
	/* Touch screens and narrow windows. 16px is the size below which iOS zooms
	   into a focused control; 44px is the tap target both platforms ask for.
	   The control selectors repeat the form-baseline ones so they outrank its
	   `font: inherit` at equal specificity (later in the same layer wins). */
	@media (pointer: coarse), (any-pointer: coarse), (max-width: 600px) {
		:is(.pt-section, .pt-pasted-form) input:not([type='checkbox']):not([type='radio']):not([type='hidden']):not([type='submit']):not([type='button']):not([type='reset']):not([type='image']),
		.wp-block-html form input:not([type='checkbox']):not([type='radio']):not([type='hidden']):not([type='submit']):not([type='button']):not([type='reset']):not([type='image']),
		:is(.pt-section, .pt-pasted-form) select,
		.wp-block-html form select,
		:is(.pt-section, .pt-pasted-form) textarea,
		.wp-block-html form textarea,
		input:not([type='checkbox']):not([type='radio']):not([type='hidden']),
		select,
		textarea {
			font-size: max(16px, 1em);
		}
		/* WooCommerce sets its own fields to the small size (15px) in unlayered CSS, which beats the rule
		   above: the shop's sort box, the quantity boxes and the login fields made an iPhone zoom in (phone
		   audit, 26 Sep 2026). An important declaration inside a layer outranks every normal one outside
		   it. Only WooCommerce's fields, so a pasted section's own field size still wins. */
		.woocommerce-page :is(.input-text, select, textarea),
		.wc-block-components-quantity-selector__input {
			font-size: max(16px, 1em) !important;
		}
		/* Core keeps menu links display:block (unlayered), so the target grows by
		   padding: half the gap to 44px above and below the line box. Browsers
		   without the lh unit fall back to .5em, which is 44px at the body size. */
		.wp-block-navigation-item__content {
			/* Border box: a nav link is content-box by default, so min-height and the padding
			   below stacked to 61px instead of the 44px asked for. */
			box-sizing: border-box;
			min-height: 44px;
			padding-block: 0.5em;
			padding-block: max(0px, calc((44px - 1lh) / 2));
		}
		/* The scheme switch and the home link (the logo, or the site name when there is no logo) keep
		   their drawn size (a 390px header row must still fit logo, menu button and switch); the tap
		   target grows around them with the same invisible, centered 44px pad as the menu buttons. The
		   logo is drawn 32px tall on a phone and the footer's site name about 38px. A short menu link
		   ("FAQ" was 33px wide on a 768px tablet) and the small arrow that opens a submenu (10px) take
		   the same pad, so the menu row keeps its spacing (phone audit #8, 26 Sep 2026). */
		.pt-scheme-toggle,
		.wp-block-site-logo a,
		.wp-block-site-title a,
		.wp-block-navigation-item__content,
		.wp-block-navigation-submenu__toggle {
			position: relative;
		}
		.pt-scheme-toggle::before,
		.wp-block-site-logo a::before,
		.wp-block-site-title a::before,
		.wp-block-navigation-item__content::before,
		.wp-block-navigation-submenu__toggle::before {
			content: '';
			position: absolute;
			top: 50%;
			left: 50%;
			width: max(44px, 100%);
			height: max(44px, 100%);
			translate: -50% -50%;
		}
		.wp-element-button,
		.wp-block-button__link,
		:is(.pt-section, .pt-pasted-form) button,
		.wp-block-html form button,
		:is(.pt-section, .pt-pasted-form) input[type='submit'],
		.wp-block-html form input[type='submit'] {
			min-height: 44px;
		}
	}
}

/* ---- Short screens: bring the menu back under one button ----------------------
   A phone held sideways is wide but very short — 844x390, or 740x360 on a smaller one.
   Core switches its overlay on width alone (600px), so at that size the full menu renders
   inline, wraps to three rows and the sticky header swallows half the screen: measured at
   51% of the viewport at 844x390 and 78% at 740x360. Height is the thing that matters here,
   so the overlay comes back on any short viewport, whatever its width. */
@media (min-width: 600px) and (max-height: 500px) {
	.wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}
	.wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}
}

/* The Home link functions.php puts in front of a not-yet-built menu's page list is one item and the list another, so
   when the pages wrapped, Home sat on a line by itself. The list's box steps aside and its pages line up after Home
   as items of the same row (and of the same column in the open menu). */
.wp-block-navigation__container > .wp-block-home-link + .wp-block-page-list {
	display: contents;
}

/* ---- The phone menu's own part (parts/menu.html, inc/menu.php) -----------------
   The whole screen, in the page's colors: the logo and the close button on one row, the menu under it, and the
   header's button (when it has one) at the bottom, as wide as the screen. The rows themselves are the rules below. */
.wp-block-navigation__overlay-container .pt-menu {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	box-sizing: border-box;
	min-height: 100vh;
	min-height: 100dvh;
	padding: 0.75rem var(--pt-gutter, 1.5rem) 1.5rem;
}
.wp-block-navigation__overlay-container .pt-menu > * {
	margin-block: 0;
}
.wp-block-navigation__overlay-container .pt-menu-top {
	align-items: center;
	min-height: 48px;
}
/* The close button is a plain button, so the browser gave it its own black: on a dark menu the X could not be seen
   (mytmaker.com, 13 Oct 2026). It takes the menu's word color, as its icon's fill already asks. */
.wp-block-navigation__overlay-container .pt-menu .wp-block-navigation-overlay-close {
	color: inherit;
}
.wp-block-navigation__overlay-container .pt-menu .wp-block-navigation {
	width: 100%;
	font-size: 1.25rem;
}
.wp-block-navigation__overlay-container .pt-menu-button {
	margin-top: auto;
}
.wp-block-navigation__overlay-container .pt-menu-button .wp-block-button,
.wp-block-navigation__overlay-container .pt-menu-button .wp-block-button__link {
	width: 100%;
	box-sizing: border-box;
	text-align: center;
}

/* ---- Overlay menu (phones, and short screens) ---------------------------------
   Core spaces the open menu with the block gap, which on a phone reads as words
   floating in white. Rows sit flush with a hairline between top-level items;
   children are indented one step, in the lighter weight, on a slightly shorter row.
   Unlayered because core's overlay rules are, and every selector below names
   `__responsive-container-content` because core's own overlay rules do: without that
   step core's `padding: 0` on a row won at (0,4,0) and the words sat at the top of each row.
   The two submenu rules name `.has-child` as well, because core's 2rem indent carries it and so
   needs one class more (0,5,0); measured on dev, 21 Sep 2026. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
	gap: 0;
}
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container > .wp-block-navigation-item + .wp-block-navigation-item,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-page-list > .wp-block-navigation-item + .wp-block-navigation-item,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-home-link + .wp-block-page-list > .wp-block-navigation-item:first-child {
	border-top: 1px solid color-mix(in srgb, currentColor 14%, transparent);
}
/* The hairlines run the menu's full width (Ben, 3 Oct 2026). Core sizes the list and each row to
   the longest word, so a line read as an underline. The list and its rows stretch; the link inside
   keeps its own width (fit-content below), so a site's pill item stays a pill and a centred menu
   stays centred. The page list is the menu of a site that has not built one yet. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-page-list,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container > .wp-block-navigation-item,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-page-list > .wp-block-navigation-item {
	align-self: stretch;
}
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-item__content {
	/* Flex, not padding arithmetic, does the centering: a site's own pill rule (a gradient
	   menu item, 24 Sep 2026) overrode padding-block, and with display:block the
	   label sat at the top of the 48px row with the spare room under it. */
	display: flex;
	align-items: center;
	box-sizing: border-box;
	width: fit-content;
	min-height: 48px;
	padding-block: 0.6em;
	padding-block: max(0px, calc((48px - 1lh) / 2));
}
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .has-child .wp-block-navigation__submenu-container {
	/* Logical, so the indent lands on the reading side of an RTL site. */
	padding-block: 0 0.35rem;
	padding-inline: 1rem 0;
}
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .has-child .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	font-weight: 300;
	display: flex;
	align-items: center;
	min-height: 40px;
	padding-block: 0.4em;
	padding-block: max(0px, calc((40px - 1lh) / 2));
}

/* ---- Keyboard focus -----------------------------------------------------------
   Two rings, so one of them always contrasts: an inner ring in the page color and
   an outer ring in the text color. A single ring cannot work everywhere — the text
   color disappears on the dark bands and the page color disappears on the page,
   and an accent ring lands invisibly on an accent button.
   Unlayered on purpose: site CSS sets box-shadow on its buttons, and a focus
   indicator has to outrank it. :focus-visible only fires for keyboard and other
   non-pointer focus, so mouse clicks are unaffected. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
	outline: 3px solid var(--wp--preset--color--contrast);
	outline-offset: 2px;
	box-shadow: 0 0 0 2px var(--wp--preset--color--base);
}

/* ---- One content box ------------------------------------------------------------
   The site has one content width and everything sits in it: 72rem of content with a
   1.5rem gutter each side, 1200px edge to edge, a common content width
   (11 Sep 2026). It never steps on tablets: below
   1200px the box is the screen minus the two gutters. The width IS WordPress's own Wide
   width (theme.json wideSize, 72rem): the owner changes it in Site Editor → Styles →
   Layout, or on the free plugin's Design → Layout card (same setting), and core blocks,
   pasted sections, the header and the footer all move together. Before 0.7.11 the box
   was a fixed 72rem here, so changing Wide width moved core blocks and nothing else.

   .pt-wrap is the content box inside a full-width section: the section prompt asks the
   AI to wrap a section's content in it, so the box comes from the theme, not from a
   number the AI made up. Full width lets the section's background reach both screen
   edges while its content keeps the box; Boxed (the block's Width control) keeps the
   whole section inside the box. The block only sets the class; what it means is the
   theme's business, so a pasted section moves between themes intact. Unlayered to
   match the rest of the layout rules here. */
:root {
	--pt-content-width: var(--wp--style--global--wide-size, 72rem);
	--pt-gutter: 1.5rem;
}
/* The side spacing IS WordPress's own root padding (theme.json styles.spacing.padding, 1.5rem; Site Editor →
   Styles → Layout → Padding, or the free plugin's Design → Layout card). Core prints it on body, not :root, and a
   custom property resolves where it is declared, so the gutter is set again here, where the padding exists
   (theme 0.8.3; before that the gutter was a fixed 1.5rem whatever the owner set). */
body {
	--pt-gutter: var(--wp--style--root--padding-left, 1.5rem);
}
.pt-section .pt-wrap {
	max-width: calc(var(--pt-content-width) + 2 * var(--pt-gutter));
	margin-inline: auto;
	padding-inline: var(--pt-gutter);
}
.pt-section--boxed {
	padding-inline: var(--pt-gutter);
}
.pt-section--boxed > :not(style):not(script) {
	max-width: var(--pt-content-width);
	margin-inline: auto;
}
/* Descendant, not child: the section prompt and every library section put the .pt-wrap inside
   the section's own <section>, so a child rule never matched and Boxed content sat one gutter
   narrower than its full-width neighbour (measured 1104 against 1152 at 1280, 21 Sep 2026). */
.pt-section--boxed .pt-wrap {
	max-width: var(--pt-content-width);
	padding-inline: 0;
}
/* A section pasted without the prompt's .pt-wrap (a plain chat answer, a page the Switch converted, an
   old footer carried over) had no content box, so its words ran to the screen edges on a computer and a
   phone (claims audit, 3 Oct 2026). Its own section takes the box as padding: a background still reaches
   both edges and the words sit where a .pt-wrap's would. Only the free plugin's classed sections (.pt-s);
   a section whose own CSS is kept lays itself out. */
.pt-section:not(.pt-section--boxed) > .pt-s:not(:has(.pt-wrap)),
.pt-section:not(.pt-section--boxed) > * > .pt-s:not(:has(.pt-wrap)) {
	padding-inline: max(var(--pt-gutter), (100% - var(--pt-content-width)) / 2);
}
/* The header and footer sit on the box too. The bars span the screen (the sticky bar's fill, a
   site's footer wave, any background); what is in them sits on the same box as every section, so
   the logo, the last menu item, the footer columns and the credit line share one edge with the
   content. Before this the logo sat 24px from the screen edge while the content started at 424px
   on a 2000px screen, 24 against 64 at 1280 (Ben, 16 Sep 2026: "everything aligned, or everything
   full width"). .pt-footer-row is the one-row and centered footer layouts (patterns/footer-row.php,
   footer-centered.php). The edge spacing is .pt-bar's, the same gutter as the sections (theme 0.8.3);
   before that each part carried an inline 1.5rem, and a part saved with it keeps it (an inline style wins)
   until the owner picks a layout again. */
.wp-site-blocks > header > .wp-block-group,
.pt-footer-groups,
.pt-footer-row,
.pt-footer-legal {
	max-width: calc(var(--pt-content-width) + 2 * var(--pt-gutter));
	margin-inline: auto;
}
.pt-bar {
	padding-inline: var(--pt-gutter);
}

/* ---- Balanced grids ---------------------------------------------------------------
   Cards fill whole rows and never leave an empty slot or one card alone on the last line (Ben,
   26 Sep 2026: "even rows unless it's an uneven number. no one line scragglers"). .pt-grid is the
   grid a section puts its cards straight inside, asked for by the section prompt like .pt-wrap, so
   the rows come from the theme and not from a column count the AI made up. Six tracks: one card
   across on a phone; two across from 40rem, an odd last card filling its row; three across from
   60rem, where a count of 3n+2 ends with two halves (five = 3 + 2, two = two halves), 3n+1 ends
   with two rows of halves (four = 2 x 2, seven = 3 + 2 + 2) and a lone card fills the row. The
   cards count themselves (:has() with :first-child:nth-last-child()), so a section can hold any
   number of cards and the rows still come out even.
   The layout (display, tracks, spans) is !important and nothing else is. The pipeline scopes a
   section's CSS under the section's id, which outranks any selector here, and AIs write
   grid-template-columns (repeat(3, 1fr), auto-fit) on their grid out of habit: that is exactly the
   row with a hole this stops. A section that wants other columns leaves the class off. The gap,
   the list reset and the step number's look sit in :where() with no weight, so a section's own CSS
   wins on looks. Unlayered, like the box above. */
:where(.pt-grid, .pt-steps) {
	gap: var(--wp--preset--spacing--40, 1.5rem);
	display: grid !important;
	grid-template-columns: repeat(6, minmax(0, 1fr)) !important;
}
:where(.pt-grid, .pt-steps) > * {
	grid-column: 1 / -1 !important;
}
@media (40rem <= width < 60rem) {
	:where(.pt-grid, .pt-steps) > * {
		grid-column: span 3 !important;
	}
	:where(.pt-grid, .pt-steps):has(> :first-child:nth-last-child(2n + 1)) > :last-child {
		grid-column: 1 / -1 !important;
	}
}
/* 3n+4, not 3n+1: a count of one is the lone card below, not half a row. */
@media (width >= 60rem) {
	:where(.pt-grid, .pt-steps) > * {
		grid-column: span 2 !important;
	}
	:where(.pt-grid, .pt-steps):has(> :first-child:nth-last-child(3n + 2)) > :nth-last-child(-n + 2),
	:where(.pt-grid, .pt-steps):has(> :first-child:nth-last-child(3n + 4)) > :nth-last-child(-n + 4) {
		grid-column: span 3 !important;
	}
	:where(.pt-grid, .pt-steps) > :only-child {
		grid-column: 1 / -1 !important;
	}
}
/* Numbered steps: <ol class="pt-steps"> (or a div) whose items each start with their heading. The
   items take the rows above; the theme numbers them in a round accent badge that sits on the
   heading's line, and whatever follows the heading runs the full width under both (Ben, 26 Sep
   2026: "make this part of theme"). Baseline, not centre: the badge's number lines up with the
   heading's first line whatever margins the section gives the heading, and a heading that wraps on
   a phone keeps the badge beside its first line. An <ol> keeps no bullets, indent or margins, so it
   sits exactly like a div. The badge rides the palette, so it follows light and dark. */
:where(.pt-steps) {
	counter-reset: pt-step;
	list-style: none;
	margin: 0;
	padding: 0;
}
/* A row of cards or steps straight after another (two grids, a grid then steps) takes the grid's own
   gap above it, so the two read as one instead of touching (Ben, 3 Oct 2026). One class of weight:
   it beats the list reset above, and a section's own CSS, printed later, still wins. */
:where(.pt-grid, .pt-steps) + :is(.pt-grid, .pt-steps) {
	margin-block-start: var(--wp--preset--spacing--40, 1.5rem);
}
:where(.pt-steps) > * {
	counter-increment: pt-step;
	column-gap: 0.75rem;
	align-items: baseline;
	align-content: start;
	display: grid !important;
	grid-template-columns: auto minmax(0, 1fr) !important;
}
:where(.pt-steps > *) > * {
	grid-column: 1 / -1 !important;
}
:where(.pt-steps > *) > :first-child {
	grid-column: 2 !important;
}
:where(.pt-steps > *)::before {
	content: counter(pt-step);
	display: grid;
	place-items: center;
	inline-size: 2.25rem;
	block-size: 2.25rem;
	border-radius: var(--pt-radius-s, 999px);
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--accent-contrast);
	font-weight: 700;
	line-height: 1;
	grid-column: 1 !important;
}

/* A raw <img>, <video> or <iframe> pasted straight into a post (an HTML block, not a figure) is a
   direct child of post-content, where core's unlayered constrained-layout rule sets max-width to the
   content size and beats the layered `img{max-width:100%}` whatever its specificity: a 2400px picture
   ran off a 390px screen. Unlayered, and min() keeps the 40rem reading column on a desktop. */
.wp-block-post-content > :is(img, video, iframe) {
	max-width: min(100%, var(--wp--style--global--content-size, 100%));
}

/* A quote reads as a quote: a rule in the accent down its reading side and slightly larger words; the name under it
   stays small. Core gives the Quote block no look of its own in a block theme, so a quote was one more paragraph
   (Paste alone walk, 13 Oct 2026, item 13). No weight (:where), so a look picked in Styles or a site's own CSS wins. */
:where(.wp-block-quote) {
	margin-inline: 0;
	padding-inline-start: 1.25rem;
	border-inline-start: 0.25rem solid var(--wp--preset--color--accent);
	font-size: var(--wp--preset--font-size--large);
}
:where(.wp-block-quote) > :first-child {
	margin-block-start: 0;
}
:where(.wp-block-quote) > :last-child {
	margin-block-end: 0;
}
:where(.wp-block-quote cite) {
	font-size: var(--wp--preset--font-size--small);
	font-style: normal;
}

/* A page shorter than the window keeps its footer at the bottom of the window (Ben, 3 Oct 2026):
   before, a coloured footer ended part way down with a strip of page colour under it. The main area
   takes the spare height; on a page taller than the window nothing moves. The admin bar's height is
   left out so a logged-in owner sees the same thing. */
.wp-site-blocks {
	display: flex;
	flex-direction: column;
	min-height: calc(100vh - var(--wp-admin--admin-bar--height, 0px));
	min-height: calc(100dvh - var(--wp-admin--admin-bar--height, 0px));
}
.wp-site-blocks > main {
	flex-grow: 1;
}

/* A template with no pasted section (the 404, a post, the archive) opens under the header with the
   room a hero has (spacing size 4: 32px on a phone, 48px on desktop) and leaves size 5 before the
   footer. Pages built from sections bring their own padding and are left alone. */
.wp-site-blocks > main:not(:has(.pt-section)) {
	padding-block: var(--wp--preset--spacing--50) var(--wp--preset--spacing--60);
}
/* A page built with Elementor gets the page's full width: in the reading column its full-width bands were
   640px wide (Elementor 4.3.3, 3 Oct 2026). Its content starts right under the header, like a page of
   sections, and the page title, when shown, keeps a hero's room above it. A page drawn by a plugin's own PHP
   template (header.php's main) is left to that template's spacing. */
.wp-block-post-content:has(> .elementor) {
	padding-inline: 0;
}
.wp-block-post-content > .elementor {
	max-width: none;
}
.wp-site-blocks > main:is(:has(> .wp-block-post-content > .elementor), .pt-plugin-page) {
	padding-block: 0;
}
.wp-site-blocks > main:has(> .wp-block-post-content > .elementor) > .pt-page-title {
	padding-block-start: var(--wp--preset--spacing--50);
}
/* The page title (templates/page.html) shows only on a page whose content has no h1; functions.php leaves
   it out of every other page before it is drawn. The block editor draws the template itself, so the same
   test is made here and the editor matches the live page. A page that opens with a section never draws it
   (functions.php keeps the h1 for screen readers); a page that opens with text and holds a section further
   down keeps the title, on the same content box as the sections and with a hero's room above it. */
.pt-page-title:has(~ .wp-block-post-content h1),
.pt-page-title:has(~ .wp-block-post-content > .wp-block-pastetheme-section:first-child) {
	display: none;
}
.wp-site-blocks > main:has(.pt-section) > .pt-page-title {
	padding-block-start: var(--wp--preset--spacing--50);
}
.wp-site-blocks > main:has(.pt-section) > .pt-page-title > *,
.wp-site-blocks > main:has(> .wp-block-post-content > section) > .pt-page-title > * {
	max-width: var(--pt-content-width);
}

/* ---- Vertical rhythm ------------------------------------------------------------
   Core puts its block gap (theme.json blockGap, 20px) under the header and between every
   two top-level blocks on a page, and nothing cancelled it. A pasted section brings its own
   ground and padding, so between two sections the gap was a strip of page color (20px on
   every switched page, 15 Sep 2026) and under the header it was the first thing
   above a hero (116px above the logo, 14 Sep). A page that opens with an
   ordinary block, a post and the 404 keep the gap. A style or script block between two
   sections (a switched page keeps its old page-wide style there) does not count as content.
   Unlayered: core's rules are :where() and unlayered, so a layered rule cannot beat them. */
.wp-site-blocks > main:has(> .wp-block-post-content > .pt-section:first-child) {
	margin-block-start: 0;
}
.wp-block-post-content > .pt-section + .pt-section,
.wp-block-post-content > :where(style, script) + .pt-section {
	margin-block-start: 0;
}

/* ---- A section pasted with the theme alone ------------------------------------------
   Without the PasteTheme plugin a section an AI wrote goes into WordPress's own Custom HTML block, which prints it
   as it is: its <section> is a direct child of the page's content, where core's constrained layout held it to the
   40rem reading column, so a hero was a small box in the middle of the page at every width (Paste alone walk, 13 Oct
   2026, item 1). A <section> at the top level of a page's or a post's content spans the screen: it leaves the column
   by the same side spacing the content has, the way core's own full-width blocks do, so its ground reaches both
   edges. Core's side margins are !important, so these are too; one element more than core's selector, so it wins.
   Core blocks keep their layout: none of them is a bare <section> there. The block editor draws the block's HTML
   inside its own wrapper (.wp-block-html), so there the wrapper leaves the column and the editor shows the page. */
.wp-block-post-content > section,
.wp-block-post-content > .wp-block-html:has(> .block-editor-inner-content > section) {
	max-width: none;
	margin-inline: calc(var(--pt-gutter) * -1) !important;
}
/* Two sections meet with no strip of page colour between them (a style or script block between them is not content),
   a page that opens with a section carrying the page's h1 starts right under the header, and a page that ends
   with a section ends on the footer. A page whose first section has no h1 keeps its title, with the room above it. */
.wp-block-post-content > section + section,
.wp-block-post-content > :where(style, script) + section {
	margin-block-start: 0;
}
.wp-site-blocks > main:has(> .wp-block-post-content > section:nth-child(1 of :not(style, script)) h1) {
	margin-block-start: 0;
	padding-block-start: 0;
}
.wp-site-blocks > main:has(> .wp-block-post-content > section:nth-last-child(1 of :not(style, script))) {
	padding-block-end: 0;
}
.wp-site-blocks > main:has(> .wp-block-post-content > section:nth-last-child(1 of :not(style, script))) + footer {
	margin-block-start: 0;
}
/* The block editor's note under a Custom HTML block (assets/editor.js) sits on the same box as the section above it. */
.wp-block-post-content > p.pt-form-note {
	max-width: var(--pt-content-width);
}
/* Inside it the one content box: the section's own side padding is the gutter, or what centres 72rem (the Wide
   width) on a wide screen, so words pasted with no CSS sit where every other page's do, with a hero's room above
   and below. No weight at all (:where, in the layer): the padding, the box sizing and anything else a section
   brings in its own CSS wins. The percentage is of the content column, which is two gutters narrower than the
   section. */
@layer pastetheme {
	:where(.wp-block-post-content > section, .wp-block-html > .block-editor-inner-content > section) {
		padding: var(--wp--preset--spacing--50) max(var(--pt-gutter), (100% + 2 * var(--pt-gutter) - var(--pt-content-width)) / 2);
		overflow-wrap: break-word;
	}
	:where(.wp-block-post-content > section, .wp-block-html > .block-editor-inner-content > section),
	:where(.wp-block-post-content > section, .wp-block-html > .block-editor-inner-content > section) * {
		box-sizing: border-box;
	}
}

/* ---- Section edges --------------------------------------------------------------
   How one full-width section meets the next. No class is today's straight line and nothing below
   applies. A child theme (through core's body_class filter) or a plugin adds pt-edge--curve, pt-edge--wave or pt-edge--custom to
   the body (custom reads its shape from --pt-edge-shape, set by whatever adds the class), and pt-edge-shade to
   shade every other section; the theme only says what the classes mean.
   The shape has no color of its own. The lower section's wrapper rides up into the one above by the
   depth and is masked into the shape, so through the cut you see the real section above, whatever its
   fill and in either scheme. The pull always equals the depth: any less and the cut shows the page
   ground, and in dark mode the shape vanished into a flat line (pastetheme.com, 8 Sep 2026).
   A pair is two full-width sections side by side, each with its .pt-wrap. Both keep the room clear
   inside their own fills, on the .pt-wrap and never in the section's own CSS: the upper keeps the whole
   depth under its content, the lower keeps depth x fit above its own (fit is measured per shape; the
   section's own top padding covers the rest of the dip). Boxed sections, a section without .pt-wrap and
   anything between two sections (a paragraph, a style block) meet straight: a full-width shape would
   chop an inset fill's corners. An inset slab is a Boxed section, or a box inside the .pt-wrap.
   The footer follows the shape on the subtle fill (the page ground when a shaded section ends the page); the last
   section keeps the room for it, or main does when the page does not end with a section (the 404, a
   post, an archive). Screen only, so paper prints straight. The block editor never carries the body
   class, so it stays straight (Ben, 8 Sep 2026: the shape is a live-page thing). Unlayered, like the
   rhythm rules above, with the gate in :where() so a site's own CSS can still override a rule. */
:root {
	/* The wave's and a custom shape's depth: 8% of the width, capped so a wide screen still reads a shape. */
	--pt-edge-depth: min(8vw, 14rem);
}
.pt-edge--curve {
	/* A slight dome: highest in the middle, the full depth at both screen edges. */
	/* Opposite bend (dipping in the middle): swap the next line for the same URL with the path M0,0Q50,200 100,0V101H0Z */
	--pt-edge-shape: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22 preserveAspectRatio=%22none%22%3E%3Cpath d=%22M0,100Q50,-100 100,100V101H0Z%22/%3E%3C/svg%3E");
	--pt-edge-fit: 0.8;
}
/* The slight curve is shallow, not as deep as the wave (Ben, 26 Sep 2026): 3% of the width, at most 3rem. It sits on
   the element with the class, so every rule that reads the depth (the pull, the mask, both reserves, the footer, main)
   follows it. :where() keeps it the weakest value there: a site's own CSS or a plugin's height on body still wins. */
:where(.pt-edge--curve) {
	--pt-edge-depth: min(3vw, 3rem);
}
.pt-edge--wave {
	/* pastetheme.com's flag wave (Ben, 8 Sep 2026): crest at 20%, dip to 92% at 77%. */
	--pt-edge-shape: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22 preserveAspectRatio=%22none%22%3E%3Cpath d=%22M0,41C7,18 13,0 20,0C33,0 62,92 77,92C86,92 93,72 100,52V101H0Z%22/%3E%3C/svg%3E");
	--pt-edge-fit: 0.62;
}
@media screen {
	.pt-edge-shade .wp-block-post-content > .pt-section:nth-child(even of .pt-section):not(.pt-section--boxed) {
		background-color: var(--wp--preset--color--subtle);
	}
	/* The lower section of a pair, and the footer: ride up by the depth, cut into the shape. */
	:where(body:is(.pt-edge--curve, .pt-edge--wave, .pt-edge--custom)) .wp-block-post-content > .pt-section:not(.pt-section--boxed):has(> * > .pt-wrap) + .pt-section:not(.pt-section--boxed):has(> * > .pt-wrap),
	:where(body:is(.pt-edge--curve, .pt-edge--wave, .pt-edge--custom)) .wp-site-blocks > footer {
		position: relative;
		margin-block-start: calc(var(--pt-edge-depth) * -1);
		-webkit-mask: var(--pt-edge-shape) top / 100% var(--pt-edge-depth) no-repeat, linear-gradient(#000, #000) bottom / 100% calc(100% - var(--pt-edge-depth) + 1px) no-repeat;
		mask: var(--pt-edge-shape) top / 100% var(--pt-edge-depth) no-repeat, linear-gradient(#000, #000) bottom / 100% calc(100% - var(--pt-edge-depth) + 1px) no-repeat;
	}
	/* The shape is drawn by the lower section's own ground, so one with no fill of its own gets the
	   page color: see-through, it showed the section above down to that one's straight bottom edge.
	   The page's own background, not the palette's base: a site whose Styles background is another
	   color showed base-colored lower sections (--pt-ground comes from functions.php and is unset
	   while the background is base). :where() keeps this under the shade and under any fill the
	   section brings. */
	:where(body:is(.pt-edge--curve, .pt-edge--wave, .pt-edge--custom) .wp-block-post-content > .pt-section:not(.pt-section--boxed):has(> * > .pt-wrap)) + .pt-section:where(:not(.pt-section--boxed):has(> * > .pt-wrap)) {
		background-color: var(--pt-ground, var(--wp--preset--color--base));
	}
	/* The room the lower section keeps above its content. An unknown shape clears the whole depth. */
	:where(body:is(.pt-edge--curve, .pt-edge--wave, .pt-edge--custom)) .wp-block-post-content > .pt-section:not(.pt-section--boxed):has(> * > .pt-wrap) + .pt-section:not(.pt-section--boxed) > * > .pt-wrap {
		padding-block-start: calc(var(--pt-edge-depth) * var(--pt-edge-fit, 1));
	}
	/* The room the upper section keeps under its content, and the last section for the footer. */
	:where(body:is(.pt-edge--curve, .pt-edge--wave, .pt-edge--custom)) .wp-block-post-content > .pt-section:not(.pt-section--boxed):has(+ .pt-section:not(.pt-section--boxed) > * > .pt-wrap) > * > .pt-wrap,
	:where(body:is(.pt-edge--curve, .pt-edge--wave, .pt-edge--custom)) .wp-block-post-content > .pt-section:not(.pt-section--boxed):last-child > * > .pt-wrap {
		padding-block-end: var(--pt-edge-depth);
	}
	/* A last section with no .pt-wrap, or a Boxed one, keeps the room below its own box, so the
	   footer's shape rises out of the page ground instead of cutting into the section's fill. */
	:where(body:is(.pt-edge--curve, .pt-edge--wave, .pt-edge--custom)) .wp-block-post-content > .pt-section:last-child:is(.pt-section--boxed, :not(:has(> * > .pt-wrap))) {
		padding-block-end: var(--pt-edge-depth);
	}
	/* A page that does not end with a section keeps the room in main. */
	:where(body:is(.pt-edge--curve, .pt-edge--wave, .pt-edge--custom)) .wp-site-blocks > main:not(:has(> .wp-block-post-content:last-child > .pt-section:last-child)) {
		padding-block-end: calc(var(--wp--preset--spacing--60) + var(--pt-edge-depth));
	}
	/* The footer's content starts below the shape's lowest point; the shape needs a fill to show. */
	:where(body:is(.pt-edge--curve, .pt-edge--wave, .pt-edge--custom)) .wp-site-blocks > footer {
		padding-block-start: var(--pt-edge-depth);
		background-color: var(--wp--preset--color--subtle);
	}
	:where(body.pt-edge-shade:is(.pt-edge--curve, .pt-edge--wave, .pt-edge--custom)) .wp-site-blocks:has(.wp-block-post-content > .pt-section:nth-child(even of .pt-section):not(.pt-section--boxed):last-child) > footer {
		background-color: var(--pt-ground, var(--wp--preset--color--base));
	}
}

/* ---- Footer ------------------------------------------------------------------
   Real headings with the links grouped under them, two columns on a phone and
   never one, and a tap target a thumb can hit. The padding sits on the two row
   wrappers in parts/footer.html, not on the lists inside them, so the footer
   keeps the same gutter as the rest of the page instead of running to the edge
   of the glass. Unlayered on purpose: core prints theme.json element styles and
   the page-list block's own CSS outside any layer, and an unlayered rule beats a
   layered one whatever the specificity. Nothing pasted carries these classes. */
.pt-footer-groups {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 2rem 1.5rem;
	align-items: start;
}
/* The group's flow layout gives every child but the first a block-gap top
   margin, which pushed every column heading but the first down one step. The
   grid gap is the only spacing between columns. A column may shrink below its content (minmax 0),
   so a long unbroken line (an email address) breaks inside it instead of pushing the page sideways
   on a phone (26 Sep 2026). */
.pt-footer-groups > * {
	margin-block-start: 0;
	overflow-wrap: anywhere;
}
/* The brand row (site title or logo, one line under it) spans the full width;
   the link groups sit beneath it, two across on a phone and four from 700px. */
.pt-footer-brand {
	grid-column: 1 / -1;
	max-width: 36rem;
}
.pt-footer-brand > * + * {
	margin-block-start: 0.5rem;
}
@media (min-width: 700px) {
	.pt-footer-groups {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}
.pt-footer-groups h2 {
	font-size: 1rem;
	margin: 0 0 0.25rem;
}
.pt-footer-groups ul {
	list-style: none;
	margin: 0;
	padding: 0;
}
/* Block links: padding on an inline anchor does not grow the hit area. On a
   mouse the rows sit close; on touch or a narrow window they grow to the 44px
   the header nav uses, with the same lh fallback. */
.pt-footer-groups li a {
	display: block;
	text-decoration: none;
	padding-block: 0.3em;
}
@media (pointer: coarse), (any-pointer: coarse), (max-width: 600px) {
	.pt-footer-groups li a {
		padding-block: 0.5em;
		padding-block: max(0px, calc((44px - 1lh) / 2));
	}
}
.pt-footer-groups li a:hover,
.pt-footer-groups li a:focus {
	text-decoration: underline;
}
/* The one-row and centered footer layouts (0.7.12): the page list runs in a line, wrapping on a
   phone, with the same block links and tap targets as the columns above. Centered when the
   layout stacks (pt-footer-stack); the row layout keeps it against the right edge. */
.pt-footer-row .wp-block-page-list {
	display: flex;
	flex-wrap: wrap;
	gap: 0 1.25rem;
	list-style: none;
	margin: 0;
	padding: 0;
}
.pt-footer-stack .wp-block-page-list {
	justify-content: center;
}
.pt-footer-row li a {
	display: block;
	text-decoration: none;
	padding-block: 0.3em;
}
@media (pointer: coarse), (any-pointer: coarse), (max-width: 600px) {
	.pt-footer-row li a {
		padding-block: 0.5em;
		padding-block: max(0px, calc((44px - 1lh) / 2));
	}
}
.pt-footer-row li a:hover,
.pt-footer-row li a:focus {
	text-decoration: underline;
}
/* Social icons (0.8.1): WordPress's Social Icons block, logos only, in the footer's own text color so
   they follow dark mode. An icon without an address prints nothing, so a footer whose owner added no
   address prints no row at all. The footer list rules above would make each icon a padded text link. */
.wp-block-social-links.pt-footer-social {
	--pt-social-pad: 0.35em;
	margin-inline: calc(-1 * var(--pt-social-pad)); /* the tap padding sits outside the text edge; outranks `.pt-footer-groups ul` */
}
@media (pointer: coarse), (any-pointer: coarse), (max-width: 600px) {
	.pt-footer-social {
		--pt-social-pad: max(0.35em, calc((44px - 1.25em) / 2));
	}
}
.pt-footer-social:not(:has(li)) {
	display: none;
}
.wp-block-social-links.pt-footer-social.is-style-logos-only .wp-social-link {
	color: inherit;
}
.pt-footer-groups .pt-footer-social li a,
.pt-footer-row .pt-footer-social li a {
	display: flex;
	padding: var(--pt-social-pad);
}
.pt-footer-stack .pt-footer-social {
	justify-content: center;
}
.pt-footer-stack > p {
	text-align: center; /* the contact line: centered like the rest, on a phone too (0.8.3) */
}
.pt-footer-legal {
	font-size: 0.85em;
}
.pt-footer-legal p {
	margin: 0;
}

/* Outside the layer on purpose: core's unlayered `.wp-block-site-logo img { height: auto }`
   collapses dimensionless SVG logos to 0x0, and lets a square raster logo render at the block's
   full width (264px tall, swallowing the header; seen on the 9 Sep install recording). The header
   owns the logo's height: 40px on desktop, whatever the file's shape, width following the aspect
   ratio (32px and 26px on phones, below). Extra specificity (img.custom-logo) outranks core. The
   Site Logo block's width setting still writes the width/height attributes and srcset sizes, so
   phones fetch a sharp candidate; a very wide banner is capped at 20rem and scaled to fit. */
.wp-block-site-logo img.custom-logo {
	height: 40px;
	width: auto;
	max-width: min(100%, 20rem);
	object-fit: contain;
}

/* A logo carries the site name (its alt text is the site name when the file has none), so the
   Site Title block beside it would say it twice. Hidden only when the logo block holds an image:
   sites without a logo keep their name, and the Site Editor's empty logo placeholder does not
   hide the title either. (Ben, 9 Sep 2026.) */
.wp-block-site-logo:has(img) + .wp-block-site-title {
	display: none;
}

/* ---- Color scheme (inc/color-scheme.php) -------------------------------------
   Everything keyed on the dark scheme below sits in @media screen. Browsers leave background
   colors out of a print by default, so a visitor whose device is dark printed white text on white
   paper, with a white logo on it (21 Sep 2026). On paper the presets fall back to the light palette
   core prints for :root, which keeps an owner's own light colors too. inc/color-scheme.php wraps
   the owner's dark colors the same way.
   Light is the theme.json palette: red accent, yellow accent-2, dark gray (#121212, was navy) words on
   the accent (Ben, 5 Sep; gray 9 Oct). Dark overrides the same preset variables in this ONE place
   with the logo's yellow leading and its red second (Ben, 9 Oct 2026, "H1": one warm family in both
   schemes; royal blue + cyan until then), dark words on the yellow, so header, footer, buttons, links and any section built
   on the presets follow the scheme. Links use --wp--custom--link: a darkened accent
   in light (red alone is under 4.5:1 on white), accent-2 lifted 30% toward white in dark (the red
   becomes #ff4d4d: 5.3:1 on the #1b1b1b footer, where the plain red read 4.3:1). Unlayered on
   purpose: presets are declared on :root by core outside any layer, and this must
   outrank them. The six dark colors are theme.json's settings.custom.dark (core prints
   them as --wp--custom--dark--*), so a style variation in styles/ can carry its own dark
   set along with its light palette (0.7.12); the hex after each is the same value, for a
   page whose global styles did not print. The owner's own dark colors (a plugin may set
   them through pastetheme_dark_colors) print after this file from inc/color-scheme.php and
   win here at equal specificity; keep the six values in step with theme.json and
   pastetheme_dark_palette_defaults(). */
:root {
	color-scheme: light;
}
@media screen {
:root[data-theme="dark"] {
	color-scheme: dark;
	--wp--preset--color--base: var(--wp--custom--dark--base, #121212);
	--wp--preset--color--contrast: var(--wp--custom--dark--contrast, #ffffff);
	--wp--preset--color--subtle: var(--wp--custom--dark--subtle, #1b1b1b);
	--wp--preset--color--accent: var(--wp--custom--dark--accent, #ffff00);
	--wp--preset--color--accent-2: var(--wp--custom--dark--accent-2, #ff0000);
	--wp--preset--color--accent-contrast: var(--wp--custom--dark--accent-contrast, #121212);
	--wp--custom--link: color-mix(in srgb, var(--wp--preset--color--accent-2) 70%, #ffffff);
}
}

/* A pasted piece that brings its own colours (inc/pasted.php gives it pt-own-colors) is written for a light page:
   its own grounds are light and its words inherit. In dark mode it keeps the light palette (printed by
   inc/pasted.php, where the owner's own colours are known), with the light ground under it and the light words in
   it, so it reads the way it was written (Paste alone walk, 13 Oct 2026, item 2: white words on a white card). The
   ground and the words carry no weight (:where), so every colour the piece sets itself wins. Form controls and
   scrollbars inside it are the light ones too. */
@media screen {
:root[data-theme="dark"] .pt-own-colors {
	color-scheme: light;
}
:where(:root[data-theme="dark"] .pt-own-colors) {
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
}
}

/* Light-only and dark-only: a section that needs a different picture per scheme (a logo drawn
   for a dark ground) carries two <img>s with these classes and the theme shows one. It has to
   be the theme's: the pipeline scopes [data-theme] selectors away from section CSS, and Safari
   drops light-dark() with url() values (every iPhone showed an empty hero on a live site,
   14 Sep 2026). Unlayered and !important so a section's own display rule cannot bring both back.
   On paper the light one is the one that shows, whatever the screen was set to. */
@media screen {
:root[data-theme="dark"] .pt-light-only,
:root:not([data-theme="dark"]) .pt-dark-only {
	display: none !important;
}
}
@media print {
	.pt-dark-only {
		display: none !important;
	}
}

/* Dark-ground logo: hidden until the scheme is dark, then it replaces the light one.
   Screen only, so a print keeps the logo drawn for a white ground. */
.wp-block-site-logo img.custom-logo--dark {
	display: none;
}
@media screen {
:root[data-theme="dark"] .wp-block-site-logo img.custom-logo--dark {
	display: inline-block;
}
/* Only when a dark sibling exists; a site with one logo keeps it in both schemes. */
:root[data-theme="dark"] .wp-block-site-logo img.custom-logo:has(+ .custom-logo--dark) {
	display: none;
}
}

@layer pastetheme {
	.pt-scheme-toggle {
		appearance: none;
		background: transparent;
		/* 50%: at 30% the button's edge was 2.0:1 against the header (WCAG 1.4.11 asks 3:1). */
		border: 1px solid color-mix(in srgb, currentColor 50%, transparent);
		border-radius: var(--pt-radius-s, 999px);
		width: 2.25rem;
		height: 2.25rem;
		padding: 0;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		color: inherit;
		cursor: pointer;
	}
	.pt-scheme-toggle svg {
		width: 1.1rem;
		height: 1.1rem;
		fill: none;
		stroke: currentColor;
		stroke-width: 2;
		stroke-linecap: round;
		stroke-linejoin: round;
	}
	.pt-scheme-toggle .pt-sun,
	:root[data-theme="dark"] .pt-scheme-toggle .pt-moon {
		display: none;
	}
	:root[data-theme="dark"] .pt-scheme-toggle .pt-sun {
		display: block;
	}
}

/* Wide lockup logos: smaller on phones so logo + menu toggle + scheme toggle share one row.
   Below 360px (the narrowest phones) the lockup drops to 26px tall; any logo is also capped
   at half the viewport so the icons always keep their row. */
@media (max-width: 600px) {
	.wp-block-site-logo img.custom-logo {
		height: 32px;
		width: auto;
		max-width: 56vw;
		object-fit: contain;
	}
}
@media (max-width: 360px) {
	.wp-block-site-logo img.custom-logo {
		height: 26px;
		max-width: 48vw;
	}
}

/* ---- WooCommerce -------------------------------------------------------------
   Bites only when WooCommerce is present (nothing else uses these classes).
   Unlayered on purpose: Woo's own stylesheets are unlayered and would beat the
   layer. Colors ride the preset variables, so html[data-theme="dark"] follows;
   `body` prefixes outrank Woo's block CSS whatever order the sheets print in. */
body {
	--wc-form-color-background: var(--wp--preset--color--base);
	--wc-form-color-text: var(--wp--preset--color--contrast);
	--wc-form-border-color: color-mix(in srgb, currentColor 30%, transparent);
	--wc-form-border-radius: var(--pt-radius-l, 1rem);
}
/* Words on the accent are the palette's Accent contrast, dark (#121212) on the brand red since 4 Oct 2026: Ben's
   call from measured pictures (white read 3.99:1 at button size, under AA's 4.5:1; dark reads 4.7:1 at any size).
   No shadow and no glow: he chose the plain look. The red itself stays #ff0000. */
/* Glassy buttons (9 Oct 2026): the plain accent with a light gel strip across the top, never a darker end, so the
   darkest point of a button is the accent itself and the words sit on the plain colour (their contrast is the palette's).
   The strip stays in the padding above the line of words (white words on the dark blue would lose contrast under it). The free plugin's "Glassy buttons" switch (Design → Colors) turns it off with
   body.pastetheme-flat-buttons; without the plugin the buttons are glassy. Outline and link-style buttons stay flat. */
:root {
	--pt-gel: linear-gradient(180deg, rgb(255 255 255 / 0.55), rgb(255 255 255 / 0.15) 18%, rgb(255 255 255 / 0) 22%);
}
body.pastetheme-flat-buttons {
	--pt-gel: none;
}
:is(.wp-element-button, .wp-block-button__link):not(.is-style-outline *, .is-style-outline, .is-link),
.pt-section :is(button[type='submit'], input[type='submit']),
:is(.pt-pasted-form, .wp-block-html form) :is(button:not([type='button'], [type='reset']), input[type='submit']),
.pt-s .btn:not(.pt-btn-quiet),
.woocommerce a.button,
body :is(.wc-block-components-button, .wc-block-cart__submit-button, .wc-block-components-checkout-place-order-button):not(.is-link) {
	background-image: var(--pt-gel);
}
/* Buttons: accent pills. a.button is the one Woo still colors itself in a block
   theme (the rest inherit theme.json via wp-element-button); the block buttons
   are listed for older Woo releases that hard-coded their own gray. */
.woocommerce a.button,
body :is(.wc-block-components-button, .wc-block-cart__submit-button, .wc-block-components-checkout-place-order-button):not(.is-link) {
	border-radius: var(--pt-radius-s, 999px);
	font-family: inherit;
	font-weight: 700;
	background-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--accent-contrast);
}
.woocommerce a.button:hover,
body :is(.wc-block-components-button, .wc-block-cart__submit-button, .wc-block-components-checkout-place-order-button):not(.is-link):hover {
	background-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--accent-contrast);
	opacity: 0.9;
}
/* Block checkout fields: Woo hard-codes white/4px; match the theme's form baseline. */
body .wc-block-components-form .wc-block-components-text-input input[type],
body .wc-block-components-form .wc-block-components-text-input input[type]:focus {
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	border-color: color-mix(in srgb, currentColor 30%, transparent);
	border-radius: var(--pt-radius-l, 1rem);
}
/* The country and state dropdowns: Woo paints the container white and the text dark gray,
   which is a white slab on a dark palette. Same baseline as the text fields. */
body .wc-blocks-components-select .wc-blocks-components-select__container {
	background-color: var(--wp--preset--color--base);
	border-radius: var(--pt-radius-l, 1rem);
}
body .wc-blocks-components-select .wc-blocks-components-select__select {
	color: var(--wp--preset--color--contrast);
	border-color: color-mix(in srgb, currentColor 30%, transparent);
	border-radius: var(--pt-radius-l, 1rem);
}
body .wc-blocks-components-select .wc-blocks-components-select__select option {
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
}
body .wc-blocks-components-select .wc-blocks-components-select__expand {
	fill: var(--wp--preset--color--contrast);
}
/* The quantity box on a product page: the same baseline (Woo leaves it browser white). */
.woocommerce .quantity .qty {
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	border: 1px solid color-mix(in srgb, currentColor 30%, transparent);
	border-radius: var(--pt-radius-l, 1rem);
}
/* Product rows that are not Woo's "responsive" grid (related products on a product page) fall to
   one full-width column under 600px; two columns, the same as the shop grid on a phone. */
@media (max-width: 599px) {
	body .wc-block-product-template.is-flex-container {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 1.25rem;
	}
	body .wc-block-product-template.is-flex-container > li {
		width: auto;
		margin: 0;
	}
}
/* Notices keep Woo's meaning color on the edge; the body is the site's own. */
.woocommerce-message,
.woocommerce-info,
.woocommerce-error,
body .wc-block-components-notice-banner:is(.is-info, .is-success, .is-error, .is-warning) {
	background-color: var(--wp--preset--color--subtle);
	color: var(--wp--preset--color--contrast);
	border-radius: var(--pt-radius-l, 1rem);
}
.woocommerce div.product p.price,
.woocommerce div.product span.price,
.woocommerce ul.products li.product .price,
body .wc-block-components-product-price {
	/* The link color, not the raw accent: a light accent on white can miss AA for normal text, while
	   --wp--custom--link is the owner's Link color, a shade of the accent by default (accent-2 in dark). */
	color: var(--wp--custom--link);
}
/* Stars: filled stars inherit the text color; the empty track is a tint of it. */
.woocommerce .star-rating::before {
	color: color-mix(in srgb, currentColor 25%, transparent);
}
