/*
Theme Name: PasteTheme
Theme URI: https://pastetheme.com
Author: Chattanooga Tshirt
Author URI: https://chattanoogatshirt.com
Description: A block theme for business websites: one typeface, a light and a dark palette, pill buttons and curved gel details, built for phones first. A static front page and a handful of pages, not a blog theme.
Version: 0.7.9
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
Tags: full-site-editing, one-column, wide-blocks, custom-colors, custom-menu, custom-logo, editor-style, translation-ready
*/

/* ---- 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%;
}

/* 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;
	}
	.pt-section {
		position: relative;
	}
	/* 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;
	}
	.pt-section input:not([type='checkbox']):not([type='radio']):not([type='hidden']):not([type='submit']):not([type='button']):not([type='reset']):not([type='image']),
	.pt-section select,
	.pt-section 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, #00141b) 50%, transparent);
		border-radius: 1rem;
		background: var(--wp--preset--color--base, #fff);
		color: var(--wp--preset--color--contrast, #00141b);
	}
	.pt-section input[type='checkbox'],
	.pt-section input[type='radio'] {
		width: auto;
		display: inline-block;
		margin-inline-end: 0.4em;
	}
	.pt-section button,
	.pt-section input[type='submit'] {
		font: inherit;
		font-weight: 600;
		padding: 0.7em 1.6em;
		border: 0;
		border-radius: 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;
	}

	/* ---- 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) {
		.pt-section input:not([type='checkbox']):not([type='radio']):not([type='hidden']):not([type='submit']):not([type='button']):not([type='reset']):not([type='image']),
		.pt-section select,
		.pt-section 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. */
		.pt-scheme-toggle,
		.wp-block-site-logo a,
		.wp-block-site-title a {
			position: relative;
		}
		.pt-scheme-toggle::before,
		.wp-block-site-logo a::before,
		.wp-block-site-title a::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,
		.pt-section button,
		.pt-section 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;
	}
}

/* ---- 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 {
	border-top: 1px solid color-mix(in srgb, currentColor 14%, transparent);
}
.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;
	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. theme.json's wideSize and root
   padding carry the same numbers for core blocks, so a pasted section and an ordinary
   paragraph share one edge. Change the width here and everything follows.

   .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: 72rem;
	--pt-gutter: 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;
}
/* 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"). The parts' own 1.5rem inline padding is the gutter. */
.wp-site-blocks > header > .wp-block-group,
.pt-footer-groups,
.pt-footer-legal {
	max-width: calc(var(--pt-content-width) + 2 * var(--pt-gutter));
	margin-inline: auto;
}

/* ---- 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;
}
: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: 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 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);
}

/* ---- 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;
}

/* ---- 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 (base 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.
	   :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(--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(--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;
}
.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, navy text on the
   accent (Ben, 5 Sep). Dark overrides the same preset variables in this ONE place
   with royal blue + cyan, 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 in dark. Unlayered on
   purpose: presets are declared on :root by core outside any layer, and this must
   outrank them. 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 below in step with
   pastetheme_dark_palette_defaults(). */
:root {
	color-scheme: light;
}
@media screen {
:root[data-theme="dark"] {
	color-scheme: dark;
	--wp--preset--color--base: #00141b;
	--wp--preset--color--contrast: #ffffff;
	--wp--preset--color--subtle: #0d1b22;
	--wp--preset--color--accent: #4169e1;
	--wp--preset--color--accent-2: #00ffff;
	--wp--preset--color--accent-contrast: #ffffff;
	--wp--custom--link: var(--wp--preset--color--accent-2);
}
}

/* 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: 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: 1rem;
}
/* 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: 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: 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: 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: 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: 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: 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: red on white is 4.0:1 and misses AA for normal text,
	   while --wp--custom--link is the same accent darkened to 5.3:1 (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);
}
