/*
Theme Name: Peptide Storefront
Theme URI: https://example.com/
Description: A standalone catalog storefront theme. Pairs with the Peptide Catalog plugin for products, categories, prices, REST-powered filtering, a Gutenberg block library, a cart and online payments. Works on its own as a normal site theme.
Version: 1.6.3
Requires at least: 6.4
Tested up to: 6.7
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: peptide-storefront
Tags: e-commerce, custom-menu, custom-logo, featured-images, block-styles, wide-blocks, translation-ready, two-columns, right-sidebar
*/

/* ==========================================================================
   HOW THIS STYLESHEET IS ORGANISED
   --------------------------------------------------------------------------
   NAMING
     Theme namespace is `ps-`. Plugin/block namespace is `pc-`.
     Strict BEM:  .ps-block  .ps-block__element  .ps-block--modifier
     State:       .is-open, .is-active, .is-stuck, .has-sale

   SPECIFICITY
     Every rule is a single class (or a class + state class). No IDs, no tag
     selectors for layout, no deep nesting. To restyle anything, write a rule
     with the same class later in the cascade - !important is never needed.

   TOKENS
     All colour, spacing, radius and type values are --ps-* custom properties
     in the :root block below. functions.php mirrors them onto the plugin's
     --pc-* tokens, so changing a token here restyles the blocks too.

   SECTIONS
     1.  Tokens
     2.  Reset & base
     3.  Utilities
     4.  Buttons
     5.  Layout shells
     6.  Announcement / topbar
     7.  Header & navigation
     8.  Search form
     9.  Hero
     10. Trust bar
     11. Sections & CTA
     12. Breadcrumbs
     13. Archives
     14. Product single
     15. Posts & pages
     16. Sidebar & widgets
     17. Pagination
     18. Empty / 404 / notices
     19. Footer
     20. Age gate
     21. Accessibility
     22. Responsive
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
	/* ----------------------------------------------------------------------
	   VERIDIAN PEPTIDES
	   Palette sampled directly from the logo artwork:
	     ground  near-black  (the logo is 85% pure black)
	     greens  #204711 -> #3d7023 -> #78b745 -> #9ad861
	     chrome  #7d7f7a -> #bdbdbc -> #f6f7f5
	   The brand is dark-first, so dark IS the theme - there is no light mode
	   to keep in sync.
	   ---------------------------------------------------------------------- */

	/* Surfaces */
	--ps-bg: #050706;
	--ps-surface: #0d120e;
	--ps-surface-alt: #141b15;
	--ps-inverse: #000000;

	/* Text - the chrome ramp from the logotype */
	--ps-ink: #f6f7f5;
	--ps-ink-soft: #bdbdbc;
	--ps-muted: #8b8d88;
	--ps-on-inverse: #e6e8e4;

	/* Lines pick up a green cast, like the logo's outlines */
	--ps-line: rgba(120, 183, 69, 0.16);
	--ps-line-strong: rgba(120, 183, 69, 0.34);

	/* Brand green */
	--ps-accent: #78b745;
	--ps-accent-hover: #9ad861;
	--ps-accent-soft: rgba(120, 183, 69, 0.14);
	--ps-accent-ink: #050706;
	--ps-accent-deep: #3d7023;
	--ps-accent-dark: #204711;

	/* Status */
	--ps-ok: #78b745;
	--ps-warn: #d9a441;
	--ps-danger: #e06666;

	/* Shape */
	--ps-radius: 10px;
	--ps-radius-sm: 6px;
	--ps-radius-lg: 16px;
	--ps-radius-pill: 999px;

	/* Depth - on black, glow reads better than drop shadow */
	--ps-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.6);
	--ps-shadow: 0 2px 6px rgba(0, 0, 0, 0.55), 0 10px 30px rgba(0, 0, 0, 0.45);
	--ps-shadow-lg: 0 4px 14px rgba(0, 0, 0, 0.6), 0 26px 60px rgba(0, 0, 0, 0.55);
	--ps-glow: 0 0 18px rgba(120, 183, 69, 0.30);

	/* Rhythm */
	--ps-gap-xs: 6px;
	--ps-gap-sm: 12px;
	--ps-gap: 24px;
	--ps-gap-lg: 40px;
	--ps-gap-xl: 72px;

	/* Measure */
	--ps-container: 1240px;
	--ps-container-narrow: 780px;
	--ps-gutter: 24px;

	/* Type */
	--ps-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	--ps-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	--ps-text-xs: 0.75rem;
	--ps-text-sm: 0.875rem;
	--ps-text: 1rem;
	--ps-text-lg: 1.125rem;
	--ps-text-xl: 1.375rem;
	--ps-text-2xl: 1.75rem;
	--ps-text-3xl: 2.25rem;
	--ps-text-4xl: 3rem;
	--ps-leading: 1.65;
	--ps-leading-tight: 1.25;

	/* Chrome gradient for the logotype-style headings */
	--ps-chrome: linear-gradient(
		176deg,
		#ffffff 0%,
		#f6f7f5 18%,
		#9a9c97 46%,
		#e8eae6 58%,
		#7d7f7a 78%,
		#cfd1cc 100%
	);

	--ps-header-height: 200px;

	/* Stacking order. Anything positioned MUST take a value from this scale,
	   otherwise it inherits `auto` and paints by DOM order - which is how a
	   sticky product panel ends up covering the sticky menu. */
	--ps-z-background: -10;
	--ps-z-content: 1;
	--ps-z-sticky: 5;
	--ps-z-submenu: 60;
	--ps-z-header: 100;
	--ps-z-gate: 1000;

	/* Feature panel: green now, not blue. Second stop fades to the ground so
	   the panel sits in the black rather than floating as a light slab. */
	--ps-panel-a: rgba(61, 112, 35, 0.55);
	--ps-panel-b: rgba(5, 7, 6, 0.25);
	--ps-panel-angle: 50deg;
	--ps-panel-radius: 15px;
	--ps-panel-base: rgba(8, 12, 9, 0.82);
	--ps-panel-ink: var(--ps-ink);
	--ps-panel-ink-soft: var(--ps-ink-soft);

	/* On-panel surfaces. The green tint is dark, so a green-on-green chip
	   disappears - these are white washes instead, which read on any panel
	   tone. `value` is the light slab spec figures sit on: at 0.4 over the
	   panel it lands mid-tone, so it takes the near-black ink, not the
	   panel ink. */
	--ps-panel-value: rgba(255, 255, 255, 0.4);
	--ps-panel-value-ink: #0a100a;
	--ps-panel-chip: rgba(255, 255, 255, 0.12);
	--ps-panel-line: rgba(255, 255, 255, 0.18);
	/* The outer edge of a panel: a solid green a shade deeper than the tint,
	   so the panel has a defined boundary against the scene behind it. */
	--ps-panel-edge: #2d612f;
}


/* ==========================================================================
   2. RESET & BASE
   ========================================================================== */

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	/* Measured by theme.js; the fallback covers the pre-JS first paint. */
	/* Cleared by the pinned notice plus the compact bar when it is showing. */
	scroll-padding-top: calc(var(--ps-announce-height, 34px) + var(--ps-minibar-height, 64px) + 16px);
}

body {
	margin: 0;
	background: var(--ps-bg);
	color: var(--ps-ink);
	font-family: var(--ps-font);
	font-size: var(--ps-text);
	line-height: var(--ps-leading);
	-webkit-font-smoothing: antialiased;
}

img,
svg,
video {
	max-width: 100%;
	height: auto;
}

a {
	color: var(--ps-accent);
	text-decoration-thickness: 1px;
	text-underline-offset: 2px;
}

a:hover {
	color: var(--ps-accent-hover);
}

button,
input,
select,
textarea {
	font: inherit;
	color: inherit;
}

:focus-visible {
	outline: 2px solid var(--ps-accent);
	outline-offset: 2px;
}

h1, h2, h3, h4, h5, h6 {
	line-height: var(--ps-leading-tight);
	font-weight: 700;
	color: var(--ps-ink);
}

/* ==========================================================================
   3. UTILITIES
   ========================================================================== */

.ps-site {
	display: flex;
	flex-direction: column;
	/* 100vh on a phone is the LARGE viewport - it assumes the URL bar is
	   scrolled away, so while the bar is showing the page is taller than the
	   screen and every full-height layout is pushed under the browser chrome.
	   100dvh tracks the viewport as it actually is. The vh line stays first
	   as the fallback for anything that does not know dvh. */
	min-height: 100vh;
	min-height: 100dvh;
}

/* Also unpositioned, for the same reason: a stacking context here would sit
   above the fixed nav panel, since it comes later in the document. */
.ps-main {
	flex: 1 1 auto;
}

/* Cart page: a lighter backing behind the cart and checkout, so they read
   against the moving background. ps-body--cart is added in ps_body_classes(). */
.ps-body--cart .ps-main {
	width: 90%;
	margin: auto;
	background: #56505078;
	border-radius: 10px;
}

.ps-content > *:first-child {
	margin-top: 0;
}

.ps-content > *:last-child {
	margin-bottom: 0;
}

.ps-content p {
	line-height: var(--ps-leading);
}

.ps-content h2 {
	margin-top: var(--ps-gap-lg);
	font-size: var(--ps-text-2xl);
}

.ps-content h3 {
	margin-top: var(--ps-gap);
	font-size: var(--ps-text-xl);
}

.ps-content ul,
.ps-content ol {
	padding-left: 1.25em;
	line-height: var(--ps-leading);
}

.ps-content blockquote {
	margin: var(--ps-gap) 0;
	padding: var(--ps-gap-sm) var(--ps-gap);
	border-left: 3px solid var(--ps-accent);
	background: var(--ps-surface);
	color: var(--ps-ink-soft);
}

.ps-content table {
	width: 100%;
	border-collapse: collapse;
}

.ps-content code {
	font-family: var(--ps-font-mono);
	font-size: 0.9em;
	background: var(--ps-surface);
	padding: 0.15em 0.4em;
	border-radius: var(--ps-radius-sm);
}

/* ==========================================================================
   4. BUTTONS
   ========================================================================== */

.ps-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 12px 24px;
	border: 1px solid transparent;
	border-radius: var(--ps-radius-sm);
	font-size: var(--ps-text-sm);
	font-weight: 650;
	line-height: 1.2;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
	white-space: nowrap;
}

.ps-button--primary {
	background: var(--ps-accent);
	border-color: var(--ps-accent);
	color: var(--ps-accent-ink);
}

.ps-button--primary:hover {
	background: var(--ps-accent-hover);
	border-color: var(--ps-accent-hover);
	color: var(--ps-accent-ink);
	box-shadow: var(--ps-glow);
}

.ps-button--ghost {
	background: transparent;
	border-color: var(--ps-line-strong);
	color: var(--ps-ink);
}

.ps-button--ghost:hover {
	border-color: var(--ps-accent);
	color: var(--ps-accent);
}

.ps-button--quiet {
	background: var(--ps-surface);
	border-color: var(--ps-line);
	color: var(--ps-ink);
}

/* ==========================================================================
   4b. FEATURE PANEL
   --------------------------------------------------------------------------
   Shared surface for the hero, the CTA block and the age gate dialog. Applied
   through a class rather than repeated, so retoning is a token change and the
   contrast guarantees hold everywhere it is used.
   ========================================================================== */

.ps-panel {
	border-radius: var(--ps-panel-radius);
	background-color: var(--ps-panel-base);
	background-image: linear-gradient(
		var(--ps-panel-angle),
		var(--ps-panel-a) 0%,
		var(--ps-panel-b) 100%
	);
	color: var(--ps-panel-ink);
}

/* Body copy on a panel steps up from --ps-muted, which does not clear AA on
   the gradient in either theme. */
.ps-panel__text {
	color: var(--ps-panel-ink-soft);
}


/* ==========================================================================
   4c. CHROME TYPE
   --------------------------------------------------------------------------
   The metallic treatment from the logotype, for the site name and the hero
   heading. Applied through a class so it never lands on body copy, where a
   gradient fill would hurt legibility.
   ========================================================================== */

.ps-chrome {
	background-image: var(--ps-chrome);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	-webkit-text-fill-color: transparent;
	/* A faint green cast under the metal, as in the artwork. */
	filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.75))
		drop-shadow(0 0 14px rgba(120, 183, 69, 0.18));
}

/* If background-clip:text is unsupported the text would vanish, so only opt in
   where it is known to work. */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
	.ps-chrome {
		background-image: none;
		color: var(--ps-ink);
		-webkit-text-fill-color: var(--ps-ink);
	}
}

/* ==========================================================================
   5. LAYOUT SHELLS
   ========================================================================== */

.ps-shell {
	width: 100%;
	max-width: var(--ps-container);
	margin: 0 auto;
	padding: var(--ps-gap-lg) var(--ps-gutter) var(--ps-gap-xl);
}

.ps-shell--page,
.ps-shell--single {
	max-width: var(--ps-container);
}

/* Narrow (Legal / Long Copy) page template: a measured column so terms and
   policy pages keep a readable line length instead of running the full shell. */
.ps-shell--narrow {
	width: 100%;
	max-width: var(--ps-container-narrow);
	margin: 0 auto;
	padding: var(--ps-gap-lg) var(--ps-gutter) var(--ps-gap-xl);
}

/* Blank Canvas page template: the blocks supply their own rhythm, so the
   article adds none of its own. */
.ps-page--canvas {
	margin: 0;
}

.ps-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--ps-gap-lg);
}

.ps-layout--sidebar {
	grid-template-columns: minmax(0, 1fr) 300px;
}

.ps-layout__main {
	min-width: 0;
}

.ps-section {
	padding: var(--ps-gap-xl) 0;
}

.ps-section--categories {
	background: var(--ps-surface);
}

.ps-section--cta {
	background: var(--ps-surface);
}

.ps-section__inner {
	width: 100%;
	max-width: var(--ps-container);
	margin: 0 auto;
	padding: 0 var(--ps-gutter);
}

/* ==========================================================================
   6. ANNOUNCEMENT / TOPBAR
   ========================================================================== */

.ps-announcement {
	/* Solid while it is the only thing up there; the compact bar slides in
	   underneath it and matches, so no seam appears. */
	background: #050706;
	border-bottom: 1px solid var(--ps-line);
	color: var(--ps-accent);
	/* 100% not 100vw: the viewport unit includes the scrollbar gutter, so it
	   resolves ~17px wider than the content area and hands back the very
	   overflow this is here to prevent. */
	max-width: 100%;
}

.ps-announcement__text {
	max-width: var(--ps-container);
	margin: 0 auto;
	padding: 9px var(--ps-gutter);
	font-size: var(--ps-text-xs);
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-align: center;
}

.ps-topbar {
	background: var(--ps-inverse);
	color: var(--ps-on-inverse);
}

.ps-topbar__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--ps-gap-sm);
	max-width: var(--ps-container);
	margin: 0 auto;
	padding: 8px var(--ps-gutter);
}

.ps-topbar__disclaimer {
	margin: 0;
	font-size: var(--ps-text-xs);
	font-weight: 600;
	letter-spacing: 0.02em;
	color: var(--ps-on-inverse);
}

.ps-topbar__contact {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--ps-gap);
}

.ps-topbar__item {
	font-size: var(--ps-text-xs);
	color: var(--ps-on-inverse);
	text-decoration: none;
}

.ps-topbar__item--phone {
	font-weight: 700;
}

.ps-topbar__item:hover {
	color: #fff;
	text-decoration: underline;
}

/* ==========================================================================
   7. HEADER & NAVIGATION
   ========================================================================== */

/* Ordinary flow. It scrolls away like any other content and never changes size
   - the compact bar in section 7a takes over once it has gone. */
/* Deliberately NOT positioned with a z-index.
 *
 * `position: relative` plus a z-index would create a stacking context, and the
 * nav lives inside this element. A descendant cannot escape its ancestor's
 * stacking context no matter what z-index it is given - so when the compact bar
 * re-anchors the nav as a fixed panel, it would still be trapped on the
 * header's layer and painted over by .ps-main. Leaving this unpositioned lets
 * the nav rise above the page as intended./*
 */
.ps-header {
	background: var(--ps-bg);
	border-bottom: 1px solid var(--ps-line);
}

.ps-header__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--ps-gap-sm);
	max-width: var(--ps-container);
	margin: 0 auto;
	/* No top padding: the brand panel is the blurred surface, and any gap here
	   shows as an unblurred strip between it and the pinned notice above -
	   which reads as a spacer rather than as part of the header. */
	padding: 0 var(--ps-gutter) 10px;
}

.ps-brand {
	background-color: #00000017 !important;
    width: 100%;
    max-width: 90%;
    backdrop-filter: blur(5px);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2px;
	flex: 0 0 auto;
	text-align: center;
}

.ps-brand__logo img {
	display: block;
	max-height: 48px;
	width: auto;
}

.ps-brand__name {
	margin: 0;
	font-size: var(--ps-text-lg);
	font-weight: 750;
	letter-spacing: 0.02em;
	text-transform: uppercase;
}

.ps-brand__link {
	color: var(--ps-ink);
	text-decoration: none;
}

.ps-brand__link:hover {
	color: var(--ps-accent);
}

/* The bundled Veridian lockup. Sized off the header height so it scales with
   the bar rather than fighting it. */
.ps-brand__name--image {
	display: block;
	line-height: 0;
}

.ps-brand__image {
	display: block;
	width: auto;
	height: clamp(150px, 22vw, 300px);
	max-width: min(92vw, 640px);
	object-fit: contain;
	/* Lift it off the black the way the artwork does. */
	filter: drop-shadow(0 0 26px rgba(120, 183, 69, 0.20));
	transition: filter 0.25s ease, height 0.28s ease;
}

.ps-brand__link:hover .ps-brand__image {
	filter: drop-shadow(0 0 34px rgba(120, 183, 69, 0.34));
}

.ps-footer__mark .ps-brand {
	width: auto;
	align-items: flex-start;
	text-align: left;
}

@media (max-width: 560px) {
	.ps-brand__image {
		height: clamp(110px, 34vw, 170px);
		max-width: 92vw;
	}
}

.ps-brand__tagline {
	margin: 0;
	font-size: var(--ps-text-xs);
	color: var(--ps-muted);
}

/* "Distribution USA" badge: top-left corner of the header, bottom-right
   corner of the footer. */
.ps-usa-badge {
	display: flex;
	justify-content: center;
	line-height: 0;
}

.ps-usa-badge__image {
	display: block;
	width: auto;
	height: 44px;
	max-width: 100%;
}

.ps-usa-badge--footer {
	justify-content: flex-end;
	margin: var(--ps-gap-sm) 0 0;
}

.ps-usa-badge--footer .ps-usa-badge__image {
	height: 56px;
}

/* Wide screens: lift the header badge out of the column into the corner.
   The inner box is positioned without a z-index, so it forms no stacking
   context and the nav keeps its own layer. */
@media (min-width: 1101px) {
	.ps-header__inner {
		position: relative;
	}

	.ps-usa-badge--header {
		position: absolute;
		top: 14px;
		left: var(--ps-gutter);
	}
}

@media (max-width: 560px) {
	.ps-usa-badge__image {
		height: 36px;
	}

	.ps-usa-badge--footer .ps-usa-badge__image {
		height: 44px;
	}
}

.ps-nav {
	flex: 0 1 auto;
	min-width: 0;
}

.ps-nav__list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 4px;
	margin: 0;
	padding: 0;
	list-style: none;
	backdrop-filter:blur(6px);
}

.ps-nav__item {
	position: relative;
}

/* Both the class and the structure.

   wp_nav_menu() gives the anchor no class of its own - the theme's filters add
   .ps-nav__link, but a menu rendered by anything else (a plugin, a different
   walker, a block) would not carry it, and the nav would come out unstyled
   with nothing obviously wrong in the CSS. Matching the descendant anchor as
   well means the styling holds whatever produced the markup. */
#ps-primary-nav .ps-nav__list a,
.ps-nav__link {
	display: block;
	padding: 9px 14px;
	border-radius: var(--ps-radius-sm);
	color: var(--ps-ink);
	font-size: var(--ps-text-sm);
	font-weight: 600;
	text-decoration: none;
}

#ps-primary-nav .ps-nav__list a:hover,
.ps-nav__link:hover {
	background: var(--ps-surface);
	color: var(--ps-accent);
}

#ps-primary-nav .current-menu-item > a,
#ps-primary-nav .current_page_item > a,
.ps-nav__item.current-menu-item .ps-nav__link,
.ps-nav__item.current_page_item .ps-nav__link {
	color: var(--ps-accent);
	background: var(--ps-accent-soft);
}

/* Submenus */
.ps-nav__list .sub-menu {
	position: absolute;
	top: 100%;
	left: 0;
	z-index: var(--ps-z-submenu);
	min-width: 220px;
	margin: 0;
	padding: 6px;
	list-style: none;
	background: var(--ps-bg);
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-radius);
	box-shadow: var(--ps-shadow-lg);
	opacity: 0;
	visibility: hidden;
	transform: translateY(4px);
	transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
}

.ps-nav__item:hover > .sub-menu,
.ps-nav__item:focus-within > .sub-menu {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}

/* Quick Links: goal on top, the product it leads to underneath. Two columns
   on wide screens so thirteen entries stay a compact panel. */
/* Block spans rather than a flex column: the nav's anchors are forced to
   display:block by an ID-level rule, which a class cannot outrank. */
.ps-quicklinks__label,
.ps-quicklinks__product {
	display: block;
}

.ps-quicklinks__product {
	margin-top: 1px;
	font-size: var(--ps-text-xs);
	font-weight: 500;
	color: var(--ps-muted);
}

@media (min-width: 1101px) {
	.ps-nav__item--quicklinks > .ps-quicklinks {
		display: grid;
		grid-template-columns: repeat(2, minmax(230px, 1fr));
		gap: 2px;
		right: 0;
		left: auto;
		min-width: 480px;
	}
}

.ps-header__actions {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--ps-gap-sm);
	flex: 0 0 auto;
}

/* One centred row holding the nav plus the search and cart. */
/* The wrapper around the primary nav. On desktop it must not exist as far as
   layout is concerned - display:contents hands the nav straight back to the
   flex row - and the narrow layout below turns it into a positioned stage. */
.ps-nav-stage {
	display: contents;
}

.ps-header__bar {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: var(--ps-gap);
	width: 100%;
	padding-top: 10px;
	border-top: 1px solid var(--ps-line);
}

.ps-header__toggle {
	display: none;
	align-items: center;
	gap: 8px;
	padding: 9px 14px;
	background: var(--ps-surface);
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-radius-sm);
	font-size: var(--ps-text-sm);
	font-weight: 650;
	cursor: pointer;
}

.ps-header__toggle-bar {
	position: relative;
	display: block;
	width: 16px;
	height: 2px;
	background: currentColor;
	box-shadow: 0 -5px 0 currentColor, 0 5px 0 currentColor;
}

/* Phone, email and hours under the lockup. Reuses the topbar item styling so
   there is one set of rules for these three pieces wherever they appear. */
.ps-brand__contact {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: var(--ps-gap-sm) var(--ps-gap);
	margin-top: 4px;
}

/* Separator dots between the items. */
.ps-brand__contact .ps-topbar__item + .ps-topbar__item::before {
	content: "";
	display: inline-block;
	width: 3px;
	height: 3px;
	margin-right: var(--ps-gap);
	border-radius: 50%;
	background: var(--ps-accent);
	vertical-align: middle;
	opacity: 0.7;
}

.ps-brand__contact .ps-topbar__item {
	color: var(--ps-ink-soft);
	font-size: var(--ps-text-sm);
}

.ps-brand__contact .ps-topbar__item--phone {
	color: var(--ps-accent);
	font-weight: 700;
	letter-spacing: 0.02em;
}

.ps-brand__contact .ps-topbar__item:hover {
	color: var(--ps-ink);
}

.ps-brand__contact .ps-topbar__item--phone:hover {
	color: var(--ps-accent-hover);
}

/* The contact block collapses to a stack once it stops fitting on one line. */
@media (max-width: 560px) {
	.ps-brand__contact {
		gap: 4px var(--ps-gap-sm);
	}

	.ps-brand__contact .ps-topbar__item + .ps-topbar__item::before {
		margin-right: var(--ps-gap-sm);
	}

	.ps-brand__contact .ps-topbar__item--hours {
		flex: 1 0 100%;
		text-align: center;
	}
}

/* ==========================================================================
   7a. PINNED NOTICE AND COMPACT BAR
   --------------------------------------------------------------------------
   The layout is deliberately split into three independent pieces:

     .ps-announce   fixed at the top, always on screen
     .ps-header     ordinary flow, scrolls away and never changes size
     .ps-minibar    fixed, slides in once the header is gone

   Nothing resizes in place, so nothing shifts the page, so the scroll position
   is never disturbed by the thing that reads it. Only `transform` animates,
   which the compositor handles without touching layout at all.
   ========================================================================== */

.ps-announce {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: calc(var(--ps-z-header) + 10);
}

/* Holds the pinned notice's place. A fixed value is safe here: the notice is a
   single line and never changes height. */
.ps-announce-spacer {
	height: var(--ps-announce-height, 34px);
	background-color: #00000061;
}

/* --------------------------------------------------------------- minibar --- */

.ps-minibar {
	position: fixed;
	/* Runs all the way to the top rather than starting below the notice. The
	   notice sits on a higher layer, so it simply shows through on top - one
	   continuous black bar instead of two stacked ones with a seam. */
	top: 0;
	left: 0;
	right: 0;
	z-index: var(--ps-z-header);
	max-width: 100%;
	background-color : #050706cf;
	border-bottom: 1px solid var(--ps-line);
	box-shadow: 0 2px 18px rgba(0, 0, 0, 0.55);

	/* Parked just above its own top edge, so it costs nothing until needed. */
	transform: translate3d(0, -100%, 0);
	visibility: hidden;
	transition: transform 0.28s ease, visibility 0s linear 0.28s;
	will-change: transform;
}

.ps-minibar.is-visible {
	transform: translate3d(0, 0, 0);
	visibility: visible;
	transition: transform 0.28s ease, visibility 0s;
}

.ps-minibar__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--ps-gap);
	max-width: var(--ps-container);
	margin: 0 auto;
	/* Clear the pinned notice, which overlays the top of this bar. */
	padding: calc(var(--ps-announce-height, 34px) + 8px) var(--ps-gutter) 8px;
}

.ps-minibar__brand {
	display: flex;
	align-items: center;
	line-height: 0;
	text-decoration: none;
}

.ps-minibar__image {
	display: block;
	width: auto;
	height: 46px;
	object-fit: contain;
	filter: drop-shadow(0 0 12px rgba(120, 183, 69, 0.22));
}

.ps-minibar__name {
	font-size: var(--ps-text-lg);
	font-weight: 750;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--ps-ink);
	line-height: 1.2;
}

.ps-minibar__actions {
	display: flex;
	align-items: center;
	gap: var(--ps-gap-sm);
}

.ps-minibar__toggle {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 9px 16px;
	border: 1px solid var(--ps-line-strong);
	border-radius: var(--ps-radius-sm);
	background: transparent;
	color: var(--ps-ink);
	font-size: var(--ps-text-sm);
	font-weight: 650;
	cursor: pointer;
}

.ps-minibar__toggle:hover {
	border-color: var(--ps-accent);
	color: var(--ps-accent);
}

.ps-minibar__toggle-bar {
	position: relative;
	display: block;
	width: 16px;
	height: 2px;
	background: currentColor;
	box-shadow: 0 -5px 0 currentColor, 0 5px 0 currentColor;
}

/* Nav opened from the compact bar.
 *
 * The nav element itself lives inside the tall header, which has scrolled out
 * of view by the time this bar appears - so opening it there would show nothing.
 * While the bar is up, the nav is re-anchored as a fixed panel directly beneath
 * it, at every width, since the header's inline nav is equally gone on desktop.
 */
/* The anchoring applies in BOTH states, not just the open one. Scoped to
   .is-open, position reverted to static the instant the class came off - so the
   panel teleported back inside the header at the start of every close and the
   height transition was never seen. Nothing here changes between states, so
   there is nothing to animate and nothing to jump. */
.ps-body--minibar .ps-nav {
	position: fixed;
	top: var(--ps-minibar-height, 64px);
	left: 0;
	right: 0;
	z-index: calc(var(--ps-z-header) - 1);
	display: block;
	background: #050706;

	/* Collapsed here too, not only on the narrow layout. This rule applies at
	   every width - the header's inline nav is gone on desktop as well once the
	   bar takes over - so without its own collapsed state the panel simply hung
	   open across the desktop page as soon as you scrolled. */
	max-height: 0;
	overflow: hidden;
	opacity: 0;
	visibility: hidden;
	transition: max-height 0.28s ease, opacity 0.2s ease,
		visibility 0s linear 0.28s;
}

/* The border and shadow are state-dependent because a 0-height panel would
   otherwise draw its border as a hairline across the screen while shut. */
.ps-body--minibar .ps-nav.is-open {
	max-height: 100%;
	opacity: 1;
	visibility: visible;
	overflow-y: auto;
	border-bottom: 1px solid var(--ps-line);
	box-shadow: 0 12px 30px rgba(0, 0, 0, 0.6);
	transition: max-height 0.32s ease, opacity 0.24s ease, visibility 0s;
}

/* Padding lives on the list rather than the panel: on the panel it would have
   to appear and disappear with the class, and padding is not something the
   height transition can absorb - the contents would shunt at both ends. */
.ps-body--minibar .ps-nav .ps-nav__list {
	flex-direction: column;
	align-items: stretch;
	justify-content: flex-start;
	gap: 2px;
	max-width: var(--ps-container);
	margin: 0 auto;
	border-top: 0;
	padding: 0 var(--ps-gutter) var(--ps-gap);
}

.ps-body--minibar .ps-nav.is-open .ps-nav__list a,
.ps-body--minibar .ps-nav.is-open .ps-nav__link {
	padding: 12px 14px;
}

/* Submenus expand inline in this panel rather than floating. */
.ps-body--minibar .ps-nav.is-open .sub-menu {
	position: static;
	opacity: 1;
	visibility: visible;
	transform: none;
	box-shadow: none;
	border: 0;
	padding-left: var(--ps-gap);
	background: transparent;
}

@media (prefers-reduced-motion: reduce) {
	.ps-minibar {
		transition: none;
	}
}

/* ==========================================================================
   8. SEARCH FORM
   ========================================================================== */

/* Collapsed-search button. Only ever shown at the narrow breakpoint at the
   foot of this file; hidden here so it costs nothing at any other width. */
.ps-search-toggle {
	display: none;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	flex: 0 0 auto;
	padding: 0;
	border: 1px solid var(--ps-line-strong);
	border-radius: var(--ps-radius-sm);
	background: var(--ps-bg);
	color: var(--ps-ink);
	cursor: pointer;
}

.ps-search-toggle:hover {
	border-color: var(--ps-accent);
	color: var(--ps-accent);
}

.ps-search-toggle[aria-expanded="true"] {
	border-color: var(--ps-accent);
	color: var(--ps-accent);
}

.ps-search-form {
	display: flex;
	align-items: stretch;
	gap: 0;
	max-width: 320px;
}

.ps-search-form__input {
	flex: 1 1 auto;
	min-width: 0;
	padding: 9px 12px;
	border: 1px solid var(--ps-line-strong);
	border-right: 0;
	border-radius: var(--ps-radius-sm) 0 0 var(--ps-radius-sm);
	background: #fffcfc29;
	color: var(--ps-accent-dark);
	font-size: var(--ps-text-sm);
}

.ps-search-form__submit {
	padding: 9px 16px;
	border: 1px solid var(--ps-accent);
	border-radius: 0 var(--ps-radius-sm) var(--ps-radius-sm) 0;
	background: var(--ps-accent);
	color: var(--ps-accent-ink);
	font-size: var(--ps-text-sm);
	font-weight: 650;
	cursor: pointer;
}

.ps-search-form__submit:hover {
	background: var(--ps-accent-hover);
	border-color: var(--ps-accent-hover);
}

/* ==========================================================================
   9. HERO
   ========================================================================== */

.ps-hero {
	background: linear-gradient(180deg, var(--ps-surface), var(--ps-bg));
	border-bottom: 1px solid var(--ps-line);
}

.ps-hero__inner {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	align-items: center;
	gap: var(--ps-gap-lg);
	width: 70%;
	max-width: var(--ps-container);
	min-height: fit-content;
	margin: 10vh auto;
	padding: var(--ps-gap-xl) var(--ps-gutter);
	border-radius: var(--ps-panel-radius);
	background-color: var(--ps-panel-base);
	background-image: linear-gradient(
		var(--ps-panel-angle),
		var(--ps-panel-a) 0%,
		var(--ps-panel-b) 100%
	);
	color: var(--ps-panel-ink);
}

.ps-hero--has-image .ps-hero__inner {
	grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
}

.ps-hero__content {
	max-width: 620px;
}

.ps-hero__eyebrow {
	margin: 0 0 var(--ps-gap-sm);
	font-size: var(--ps-text-xs);
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--ps-accent);
	opacity: 1;
}

.ps-hero__heading {
	margin: 0 0 var(--ps-gap-sm);
	font-size: var(--ps-text-4xl);
	font-weight: 780;
	letter-spacing: -0.02em;
	background-image: var(--ps-chrome);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: transparent;
	filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.7))
		drop-shadow(0 0 20px rgba(120, 183, 69, 0.16));
}

@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
	.ps-hero__heading {
		background-image: none;
		color: var(--ps-ink);
		-webkit-text-fill-color: var(--ps-ink);
	}
}

.ps-hero__text {
	margin: 0 0 var(--ps-gap);
	font-size: var(--ps-text-lg);
	line-height: var(--ps-leading);
	/* --ps-muted measures 2.16:1 on the panel gradient; ink-soft clears AA. */
	color: var(--ps-panel-ink-soft);
}

.ps-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--ps-gap-sm);
}

.ps-hero__media {
	position: relative;
}

.ps-hero__image {
	display: block;
	width: 100%;
	border-radius: var(--ps-radius-lg);
	box-shadow: var(--ps-shadow-lg);
}

/* ==========================================================================
   10. TRUST BAR
   ========================================================================== */

.ps-trust {
	border-bottom: 1px solid var(--ps-line);
	background: var(--ps-bg);
}

.ps-trust__list {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--ps-gap);
	max-width: var(--ps-container);
	margin: 0 auto;
	padding: var(--ps-gap) var(--ps-gutter);
	list-style: none;
}

.ps-trust__item {
	display: flex;
	align-items: center;
	gap: 10px;
}

.ps-trust__mark {
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: var(--ps-accent-soft);
	border: 2px solid var(--ps-accent);
	box-shadow: var(--ps-glow);
}

.ps-trust__text {
	font-size: var(--ps-text-sm);
	font-weight: 600;
	color: var(--ps-ink-soft);
}

/* ==========================================================================
   11. SECTIONS & CTA
   ========================================================================== */

.ps-cta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--ps-gap);
	padding: var(--ps-gap-lg);
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-panel-radius);
	background-color: var(--ps-panel-base);
	background-image: linear-gradient(
		var(--ps-panel-angle),
		var(--ps-panel-a) 0%,
		var(--ps-panel-b) 100%
	);
	color: var(--ps-panel-ink);
	box-shadow: var(--ps-shadow-sm);
}

.ps-cta__body {
	flex: 1 1 380px;
}

.ps-cta__heading {
	margin: 0 0 6px;
	font-size: var(--ps-text-2xl);
}

.ps-cta__text {
	margin: 0;
	color: var(--ps-panel-ink-soft);
}

/* ==========================================================================
   12. BREADCRUMBS
   ========================================================================== */

.ps-crumbs {
	margin-bottom: var(--ps-gap);
}

.ps-crumbs__list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: var(--ps-text-xs);
}

.ps-crumbs__item {
	display: flex;
	align-items: center;
	gap: 8px;
	color: var(--ps-muted);
}

.ps-crumbs__item + .ps-crumbs__item::before {
	content: "/";
	color: var(--ps-line-strong);
}

.ps-crumbs__link {
	color: var(--ps-muted);
	text-decoration: none;
}

.ps-crumbs__link:hover {
	color: var(--ps-accent);
	text-decoration: underline;
}

.ps-crumbs__current {
	color: var(--ps-ink);
	font-weight: 600;
}

/* ==========================================================================
   13. ARCHIVES
   ========================================================================== */

.ps-archive__header {
	margin-bottom: var(--ps-gap-lg);
}

.ps-archive__header--term {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--ps-gap);
	align-items: center;
}

.ps-archive__header--has-image {
	grid-template-columns: 280px minmax(0, 1fr);
}

.ps-archive__media {
	overflow: hidden;
	border-radius: var(--ps-radius);
	border-top: 4px solid var(--ps-term-accent, var(--ps-accent));
}

.ps-archive__image {
	display: block;
	width: 100%;
	aspect-ratio: 3 / 2;
	object-fit: cover;
}

.ps-archive__eyebrow {
	margin: 0 0 4px;
	font-size: var(--ps-text-xs);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ps-accent);
}

.ps-archive__title {
	margin: 0 0 var(--ps-gap-sm);
	font-size: var(--ps-text-3xl);
	letter-spacing: -0.02em;
}

.ps-archive__description {
	max-width: var(--ps-container-narrow);
	color: var(--ps-muted);
}

.ps-archive__count {
	margin: var(--ps-gap-sm) 0 0;
	font-size: var(--ps-text-sm);
	color: var(--ps-muted);
}

.ps-archive__notice {
	margin: var(--ps-gap-sm) 0 0;
	padding: 10px 14px;
	border-left: 3px solid var(--ps-warn);
	background: var(--ps-surface);
	font-size: var(--ps-text-sm);
	color: var(--ps-ink-soft);
}

.ps-archive__grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--ps-gap);
}

.ps-archive__children {
	margin-top: var(--ps-gap-xl);
}

/* ==========================================================================
   14. PRODUCT SINGLE
   ========================================================================== */

.ps-product__top {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: var(--ps-gap-lg);
	margin-bottom: var(--ps-gap-xl);
}

.ps-product__details {
	width: 80%;
	max-width: var(--ps-container-narrow);
	margin: 0 auto;
	/* No side padding on the panel itself - see the rules below. Vertical only,
	   so the first and last blocks still clear the edge. */
	padding: 5px 0 10px;
	border-radius: var(--ps-radius);
	/* The feature-panel green, flat rather than gradient, so the long body copy
	   sits on one even tint. Tokens, so it retones with the panel. */
	border: 1px solid var(--ps-panel-edge);
	background-color: var(--ps-panel-a);
	backdrop-filter: blur(6px);
	color: var(--ps-panel-ink);
}

/* Only the running text is indented - listed by element rather than by
   "everything except", so a block added later sits full width by default and
   has to be named to be inset. The spec table, the buy row and any catalog
   block keep the panel's whole width, which is what they are for.

   Lists are included deliberately: a ul left at full width while the
   paragraphs around it are inset reads as a mistake, and its markers then hang
   outside the text column instead of beside it. */
.ps-product__details > p,
.ps-product__details > h1,
.ps-product__details > h2,
.ps-product__details > h3,
.ps-product__details > h4,
.ps-product__details > h5,
.ps-product__details > h6,
.ps-product__details > ul,
.ps-product__details > ol,
.ps-product__details > dl,
.ps-product__details > blockquote,
.ps-product__details > .wp-block-heading,
.ps-product__details > .wp-block-paragraph,
.ps-product__details > .wp-block-list,
.ps-product__details > .wp-block-quote {
	width: 70%;
	margin-left: 15%;
}

/* The indent is a luxury of a wide panel. As the screen narrows, 70% of an
   already narrow column stops being a reading measure and starts being a
   gutter with words in it, so the text is handed the width back in two steps
   and the offset goes with it. */
@media (max-width: 900px) {
	.ps-product__details > p,
	.ps-product__details > h1,
	.ps-product__details > h2,
	.ps-product__details > h3,
	.ps-product__details > h4,
	.ps-product__details > h5,
	.ps-product__details > h6,
	.ps-product__details > ul,
	.ps-product__details > ol,
	.ps-product__details > dl,
	.ps-product__details > blockquote,
	.ps-product__details > .wp-block-heading,
	.ps-product__details > .wp-block-paragraph,
	.ps-product__details > .wp-block-list,
	.ps-product__details > .wp-block-quote {
		width: 85%;
		margin-left: 10%;
	}
}

@media (max-width: 600px) {
	.ps-product__details > p,
	.ps-product__details > h1,
	.ps-product__details > h2,
	.ps-product__details > h3,
	.ps-product__details > h4,
	.ps-product__details > h5,
	.ps-product__details > h6,
	.ps-product__details > ul,
	.ps-product__details > ol,
	.ps-product__details > dl,
	.ps-product__details > blockquote,
	.ps-product__details > .wp-block-heading,
	.ps-product__details > .wp-block-paragraph,
	.ps-product__details > .wp-block-list,
	.ps-product__details > .wp-block-quote {
		width: auto;
		/* An even inset now rather than an offset: on a phone the asymmetry
		   reads as a layout fault, not as a design. */
		margin-left: 0;
		padding-left: 16px;
		padding-right: 16px;
	}

	/* Markers would otherwise sit in that padding, outside the text. */
	.ps-product__details > ul,
	.ps-product__details > ol,
	.ps-product__details > .wp-block-list {
		padding-left: 34px;
	}
}

/* The plugin's spec table on the panel: the dark label cells and hairline
   green borders both vanish, so labels take a light wash and the values the
   full slab. */
.ps-product__details .pc-specs,
.ps-product__details .pc-specs__row {
	border-color: var(--ps-panel-line);
}

.ps-product__details .pc-specs__label {
	background: var(--ps-panel-chip);
	color: var(--ps-panel-ink);
}

.ps-product__details .pc-specs__value {
	background: var(--ps-panel-value);
	color: var(--ps-panel-value-ink);
	font-weight: 600;
}

.ps-product__related {
	margin-top: var(--ps-gap-xl);
	padding-top: var(--ps-gap-lg);
	border-top: 1px solid var(--ps-line);
}

/* Gallery */
.ps-gallery__main {
	position: relative;
	overflow: hidden;
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-radius-lg);
	background: var(--ps-surface);
	aspect-ratio: 1 / 1;
}

.ps-gallery__image {
	width: auto;
    margin: auto;
	height: 100%;
	object-fit: cover;
	display: block;
}

.ps-gallery__placeholder {
	position: absolute;
	inset: 0;
	background: linear-gradient(135deg, var(--ps-surface), var(--ps-surface-alt));
}

.ps-gallery__thumbs {
	display: flex;
	flex-wrap: wrap;
	gap: var(--ps-gap-sm);
	margin: var(--ps-gap-sm) 0 0;
	padding: 0;
	list-style: none;
}

.ps-gallery__thumb {
	display: block;
	width: 72px;
	height: 72px;
	padding: 0;
	overflow: hidden;
	border: 2px solid var(--ps-line);
	border-radius: var(--ps-radius-sm);
	background: var(--ps-surface);
	cursor: pointer;
}

.ps-gallery__thumb.is-active {
	border-color: var(--ps-accent);
}

.ps-gallery__thumb-image {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* Purchase panel */
.ps-purchase {
	position: sticky;
	/* Without an explicit z-index this paints over the sticky header, because
	   it is positioned and comes later in the document. */
	z-index: var(--ps-z-sticky);
	top: calc(var(--ps-announce-height, 34px) + var(--ps-minibar-height, 64px) + 20px);
	display: flex;
	flex-direction: column;
	gap: var(--ps-gap-sm);
	/* Same backing as .ps-product__details, so the two halves of the page
	   read as one surface. It goes on .ps-purchase rather than the column
	   wrapper so the panel hugs its content and travels with the sticky. */
	padding: 20px;
	border: 1px solid var(--ps-panel-edge);
	border-radius: var(--ps-radius);
	background-color: var(--ps-panel-a);
	backdrop-filter: blur(6px);
	color: var(--ps-panel-ink);
}

.ps-purchase__eyebrow {
	font-size: var(--ps-text-xs);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	/* The lighter green: the base accent only clears 4.7:1 on the panel. */
	color: var(--ps-accent-hover);
	text-decoration: none;
}

.ps-purchase__eyebrow:hover {
	text-decoration: underline;
}

.ps-purchase__title {
	margin: 0;
	font-size: var(--ps-text-3xl);
	letter-spacing: -0.02em;
}

.ps-purchase__facts {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ps-purchase__fact {
	padding: 4px 10px;
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-radius-pill);
	background: var(--ps-surface);
	font-size: var(--ps-text-xs);
	font-weight: 650;
	color: var(--ps-ink-soft);
}

.ps-purchase__price {
	font-size: var(--ps-text-2xl);
}

.ps-purchase__stock {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--ps-gap-sm);
	margin: 0;
}

.ps-purchase__sku {
	font-size: var(--ps-text-xs);
	color: var(--ps-muted);
}

.ps-purchase__blurb {
	margin: 0;
	color: var(--ps-muted);
	line-height: var(--ps-leading);
}

.ps-purchase__action {
	margin-top: var(--ps-gap-xs);
}

.ps-purchase__payments {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	padding-top: var(--ps-gap-sm);
	border-top: 1px solid var(--ps-line);
}

.ps-purchase__payments-label {
	font-size: var(--ps-text-xs);
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--ps-muted);
}

.ps-purchase__payment {
	padding: 4px 10px;
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-radius-pill);
	background: var(--ps-surface);
	font-size: var(--ps-text-xs);
	font-weight: 600;
	color: var(--ps-ink-soft);
}

.ps-purchase__tags {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.ps-purchase__tag {
	padding: 3px 9px;
	border-radius: var(--ps-radius-sm);
	background: var(--ps-accent-soft);
	color: var(--ps-accent);
	font-size: var(--ps-text-xs);
	font-weight: 600;
	text-decoration: none;
}

.ps-purchase__tag:hover {
	background: var(--ps-accent);
	color: var(--ps-accent-ink);
}

/* --- On the green panel, the page-level greys and the plugin's dark chips
       both lose contrast, so everything inside re-tones. These sit AFTER the
       base rules above: they are single-class too, so the cascade decides. --- */

.ps-purchase__sku,
.ps-purchase__blurb {
	color: var(--ps-panel-ink-soft);
}

.ps-purchase .pc-price,
.ps-purchase .pc-variants__label,
.ps-purchase .pc-variants__price {
	color: var(--ps-panel-ink);
}

.ps-purchase .pc-price__prefix,
.ps-purchase .pc-price__original,
.ps-purchase .pc-price__request,
.ps-purchase .pc-variants__title,
.ps-purchase .pc-buy__note {
	color: var(--ps-panel-ink-soft);
}

/* Spec values - size, purity and the variant rows - sit on the light slab
   with near-black ink. */
.ps-purchase__fact,
.ps-purchase .pc-variants__item {
	border-color: var(--ps-panel-line);
	background: var(--ps-panel-value);
	color: var(--ps-panel-value-ink);
}

.ps-purchase .pc-variants__label,
.ps-purchase .pc-variants__price {
	color: var(--ps-panel-value-ink);
}

.ps-purchase .pc-variants__status {
	/* Sits on the light value slab, so it goes darker, not lighter. */
	color: #3d0a0a;
}

/* Chips that are not values keep the panel tone, just lifted off it. */
.ps-purchase .pc-stock {
	background: var(--ps-panel-chip);
	color: var(--ps-panel-ink-soft);
}

.ps-purchase .pc-stock--instock {
	color: var(--ps-accent-hover);
}

/* Warn and danger only clear 3.5:1 and 2.4:1 against the panel, so the
   status chips take lifted tints of the same hues. */
.ps-purchase .pc-stock--lowstock,
.ps-purchase .pc-stock--preorder {
	color: #edc77c;
}

.ps-purchase .pc-stock--outofstock {
	color: #f5b5b5;
}

.ps-purchase__payments {
	border-top-color: var(--ps-panel-line);
}

.ps-purchase__payments-label {
	color: var(--ps-panel-ink-soft);
}

.ps-purchase__payment {
	border-color: var(--ps-panel-line);
	background: var(--ps-panel-chip);
	color: var(--ps-panel-ink-soft);
}

.ps-purchase__tag {
	background: var(--ps-panel-chip);
	color: var(--ps-accent-hover);
}

.ps-purchase__tag:hover {
	background: var(--ps-accent-hover);
	color: var(--ps-accent-ink);
}

/* ==========================================================================
   15. POSTS & PAGES
   ========================================================================== */

.ps-page__header,
.ps-post__header {
	margin-bottom: var(--ps-gap);
}

.ps-page__title,
.ps-post__title {
	margin: 0;
	font-size: var(--ps-text-3xl);
	letter-spacing: -0.02em;
}

.ps-page__media,
.ps-post__media {
	margin: 0 0 var(--ps-gap-lg);
	overflow: hidden;
	border-radius: var(--ps-radius-lg);
}

.ps-page__image,
.ps-post__image {
	display: block;
	width: 100%;
}

.ps-post__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--ps-gap-sm);
	margin: var(--ps-gap-xs) 0 0;
	font-size: var(--ps-text-sm);
	color: var(--ps-muted);
}

.ps-posts {
	display: grid;
	gap: var(--ps-gap-lg);
}

/* Each post in a list sits on its own lighter backing, matching the cart
   page, instead of a divider line. */
.ps-post--summary {
	display: grid;
	grid-template-columns: 240px minmax(0, 1fr);
	gap: var(--ps-gap);
	align-items: start;
	padding: var(--ps-gap);
	background: #56505078;
	border-radius: 10px;
}

.ps-post--summary .ps-post__title {
	font-size: var(--ps-text-xl);
}

.ps-post__link {
	color: var(--ps-ink);
	text-decoration: none;
}

.ps-post__link:hover {
	color: var(--ps-accent);
}

.ps-post__excerpt {
	color: var(--ps-muted);
}

.ps-post__more {
	font-size: var(--ps-text-sm);
	font-weight: 650;
	text-decoration: none;
}

.ps-post__more:hover {
	text-decoration: underline;
}

/* --------------------------------------------------------------------------
   Readable Article post template.

   The body copy sits on a solid panel rather than on the moving night sky, and
   the measure is held near 68 characters - long enough not to feel cramped,
   short enough that the eye finds the start of the next line without hunting.
   -------------------------------------------------------------------------- */
.ps-shell--article {
	width: 100%;
	max-width: 60rem;
	margin: 0 auto;
	padding: var(--ps-gap-lg) var(--ps-gutter) var(--ps-gap-xl);
}

/* Wider than the panel, so the panel reads as the page rather than as a card
   that happens to contain a picture. */
.ps-article__media {
	margin: 0 0 calc(var(--ps-gap-lg) * -1);
	border-radius: var(--ps-radius);
	overflow: hidden;
}

.ps-article__image {
	display: block;
	width: 100%;
	height: auto;
}

.ps-article__caption {
	margin-top: 6px;
	font-size: var(--ps-text-xs);
	color: var(--ps-muted);
	text-align: center;
}

.ps-article__panel {
	position: relative;
	max-width: 44rem;
	margin: var(--ps-gap-lg) auto 0;
	padding: var(--ps-gap-lg) var(--ps-gap);
	border: 1px solid var(--ps-panel-edge);
	border-radius: var(--ps-radius);

	/* The one place on the site that inverts.
	
	   The rest of the theme is dark-first, which suits a shopfront: short
	   labels, product shots, a lot of contrast. Long prose is the opposite
	   case - light text on black holds the eye badly over several screens, so
	   the article panel flips to dark-on-light and reads like paper.
	
	   Done by redefining the tokens rather than by setting colours on each
	   element: everything inside - the content styles, the tag list, the block
	   editor's own output - already reads these, so they all invert together
	   and nothing is left behind at the old value.
	
	   Solid, not translucent. A blur still lets the canvas move behind the
	   text, which is exactly what makes long copy tiring to read here. */
	--ps-ink: #14201a;
	--ps-ink-soft: #33443a;
	--ps-muted: #5c6b60;
	--ps-line: rgba(20, 32, 26, 0.14);
	--ps-line-strong: rgba(20, 32, 26, 0.3);
	--ps-surface: #ffffff;
	--ps-surface-alt: #eef1ec;
	/* The bright accent fails contrast on a light ground - the deep green from
	   the same ramp clears it comfortably. */
	--ps-accent: var(--ps-accent-deep);
	--ps-accent-hover: var(--ps-accent-dark);
	--ps-accent-soft: rgba(61, 112, 35, 0.1);
	--ps-accent-ink: #ffffff;

	/* 96% rather than fully opaque, with the scene blurred behind it.
	
	   Straight translucency at 86% left the starfield visibly moving under the
	   copy, which is the thing that makes long-form tiring here. The blur kills
	   the motion - stars stop being points that travel and become a soft wash -
	   while the last 4% of transparency keeps the scene's colour bleeding
	   through the panel, so it still belongs to the page instead of sitting on
	   it like a sheet of paper.
	
	   Where backdrop-filter is unsupported there is nothing to soften the
	   motion, so that case goes fully opaque instead. */
	background-color: #f6f7f5f5;
	-webkit-backdrop-filter: blur(14px) saturate(1.1);
	backdrop-filter: blur(14px) saturate(1.1);
	color: var(--ps-ink);
}

@supports not (backdrop-filter: blur(1px)) {
	.ps-article__panel {
		background-color: #f6f7f5;
	}
}

.ps-article__header {
	margin-bottom: var(--ps-gap);
	padding-bottom: var(--ps-gap);
	border-bottom: 1px solid var(--ps-line);
}

.ps-article__title {
	margin: 0 0 10px;
	font-size: var(--ps-text-3xl);
	line-height: 1.15;
	letter-spacing: -0.02em;
	text-wrap: balance;
}

.ps-article__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 0;
	font-size: var(--ps-text-xs);
	color: var(--ps-muted);
}

.ps-article__dot {
	opacity: 0.5;
}

/* The reading column. 68ch is the measure; the panel padding does the rest. */
.ps-article__content {
	max-width: 68ch;
	font-size: 1.05rem;
	line-height: 1.75;
}

.ps-article__content > * + * {
	margin-top: 1.1em;
}

.ps-article__content h2,
.ps-article__content h3 {
	margin-top: 2em;
	line-height: 1.3;
}

.ps-article__content img,
.ps-article__content figure {
	border-radius: var(--ps-radius-sm);
}

/* Long-form gets a larger first line of each new section rather than a drop
   cap, which fights the sans body face. */
.ps-article__content > p:first-of-type {
	font-size: 1.12rem;
	color: var(--ps-ink);
}

/* Every paragraph opens on a weighted green initial.
   
   Posts only - it is a reading device, and it would be noise on a product
   description or a policy page. Both selectors are posts: the first is the
   Readable Article template, the second a post still on the default single.
   
   ::first-letter accepts only a small set of properties, and text-stroke is
   one of them. The stroke is what keeps the letter defined at body size -
   without it, a bold accent character on a light ground reads as a colour
   mistake rather than as a deliberate initial. paint-order puts the stroke
   under the fill so the letterform stays the shape the typeface drew.
   
   The browser applies this to the first typographic letter unit, so an opening
   quote mark or bracket is styled along with the letter it belongs to, which
   is the correct behaviour. */
.ps-article__content p::first-letter,
.ps-post--single .ps-post__content p::first-letter {
	font-weight: 800;
	/* The button green, deliberately not var(--ps-accent): inside the article
	   panel that token is remapped to the deep green for body-text contrast,
	   and this initial is meant to match the buttons elsewhere on the site
	   rather than the links beside it. The dark stroke below is what carries
	   its definition on the light panel - the fill alone would not. */
	color: #78b745;
	-webkit-text-stroke: 0.6px var(--ps-accent-dark);
	paint-order: stroke fill;
}

.ps-article__footer {
	margin-top: var(--ps-gap-lg);
	padding-top: var(--ps-gap);
	border-top: 1px solid var(--ps-line);
}

/* Previous / next */
/* Two fixed columns, not auto-fit.
   
   The newest post has no next and the oldest has no previous, and with
   auto-fit the one surviving link stretched across the whole row - which
   reads as "this is the only way on" rather than as one of a pair. Explicit
   column placement keeps back on the left and forward on the right whether
   there are two links or one, so the empty side stays visibly empty. */
.ps-article__nav {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--ps-gap-sm);
	max-width: 44rem;
	margin: var(--ps-gap-lg) auto 0;
}

.ps-article__nav-link--prev {
	grid-column: 1;
}

.ps-article__nav-link--next {
	grid-column: 2;
}

/* Outside the panel, so these stay on the site's dark palette - they belong to
   the page around the article rather than to the article. */
.ps-article__nav-link {
	display: block;
	padding: 12px 14px;
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-radius-sm);
	background: var(--ps-surface);
	color: var(--ps-ink);
	text-decoration: none;
	transition: border-color 0.2s ease;
}

.ps-article__nav-link:hover {
	border-color: var(--ps-accent);
}

.ps-article__nav-link--next {
	text-align: right;
}

.ps-article__nav-label {
	display: block;
	font-size: var(--ps-text-xs);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ps-accent);
	margin-bottom: 2px;
}

.ps-article__nav-title {
	display: block;
	font-size: var(--ps-text-sm);
	line-height: 1.35;
}

@media (max-width: 780px) {
	/* Stacked on a phone: two of these side by side leaves each title clipped
	   to a couple of words, which defeats the point of showing the title. */
	.ps-article__nav {
		grid-template-columns: 1fr;
	}

	.ps-article__nav-link--prev,
	.ps-article__nav-link--next {
		grid-column: 1;
	}

	.ps-article__nav-link--next {
		text-align: left;
	}

	.ps-article__panel {
		padding: var(--ps-gap) var(--ps-gap-sm);
	}

	.ps-article__title {
		font-size: var(--ps-text-2xl);
	}

	.ps-article__content {
		font-size: 1rem;
	}
}

/* --------------------------------------------------------------------------
   Contact page template.
   -------------------------------------------------------------------------- */
.ps-contact__details {
	margin: var(--ps-gap-lg) 0;
	padding: var(--ps-gap);
	border: 1px solid var(--ps-panel-edge);
	border-radius: var(--ps-radius);
	background-color: var(--ps-panel-a);
	backdrop-filter: blur(6px);
	color: var(--ps-panel-ink);
}

.ps-contact__list {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
	gap: var(--ps-gap);
	margin: 0;
}

.ps-contact__item {
	margin: 0;
}

.ps-contact__label {
	margin: 0 0 2px;
	font-size: var(--ps-text-xs);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ps-panel-ink-soft);
}

.ps-contact__value {
	margin: 0;
	font-size: var(--ps-text-sm);
	line-height: var(--ps-leading);
}

.ps-contact__value a {
	color: inherit;
}

.ps-contact__heading {
	margin: var(--ps-gap-xl) 0 var(--ps-gap);
	padding-top: var(--ps-gap);
	border-top: 1px solid var(--ps-line);
	font-size: var(--ps-text-lg);
}

/* --------------------------------------------------------------------------
   Blog page template. The lead post is the same .ps-post as the list items,
   only larger - one set of rules, two sizes - so a change to post styling does
   not have to be made twice.
   -------------------------------------------------------------------------- */
.ps-blog__intro {
	margin-bottom: var(--ps-gap-lg);
}

.ps-blog__heading {
	margin: var(--ps-gap-xl) 0 var(--ps-gap);
	padding-top: var(--ps-gap);
	border-top: 1px solid var(--ps-line);
	font-size: var(--ps-text-lg);
}

.ps-post--lead {
	margin-bottom: var(--ps-gap-lg);
	padding: var(--ps-gap);
	background: #56505078;
	border-radius: 10px;
}

.ps-post--lead .ps-post__media {
	display: block;
	margin-bottom: var(--ps-gap);
}

.ps-post--lead .ps-post__title {
	font-size: var(--ps-text-2xl);
}

.ps-post__eyebrow {
	margin: 0 0 6px;
	font-size: var(--ps-text-xs);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ps-accent);
}

.ps-post__tags {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin: var(--ps-gap) 0 0;
	padding: 0;
	list-style: none;
}

.ps-result {
	padding-bottom: var(--ps-gap);
	margin-bottom: var(--ps-gap);
	border-bottom: 1px solid var(--ps-line);
}

.ps-result__title {
	margin: 0 0 4px;
	font-size: var(--ps-text-lg);
}

.ps-result__link {
	color: var(--ps-ink);
	text-decoration: none;
}

.ps-result__link:hover {
	color: var(--ps-accent);
}

.ps-result__url {
	margin: 0 0 6px;
	font-size: var(--ps-text-xs);
	color: var(--ps-ok);
	word-break: break-all;
}

.ps-result__excerpt {
	color: var(--ps-muted);
	font-size: var(--ps-text-sm);
}

.ps-search__heading {
	margin: 0 0 var(--ps-gap);
	font-size: var(--ps-text-xl);
}

.ps-search__products {
	margin-bottom: var(--ps-gap-xl);
}

.ps-search__grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--ps-gap);
}

/* ==========================================================================
   16. SIDEBAR & WIDGETS
   ========================================================================== */

.ps-sidebar {
	/* display: grid; */
	gap: var(--ps-gap);
	align-content: start;
	display: none;
}

.ps-widget {
	padding: var(--ps-gap);
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-radius);
	background: var(--ps-bg);
}

.ps-widget__title {
	margin: 0 0 var(--ps-gap-sm);
	font-size: var(--ps-text-sm);
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--ps-muted);
}

.ps-widget ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

.ps-widget li {
	padding: 6px 0;
	border-bottom: 1px solid var(--ps-line);
	font-size: var(--ps-text-sm);
}

.ps-widget li:last-child {
	border-bottom: 0;
}

/* ==========================================================================
   17. PAGINATION
   ========================================================================== */

.ps-pagination {
	margin-top: var(--ps-gap-lg);
}

.ps-pagination__list {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 6px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ps-pagination__item .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 40px;
	height: 40px;
	padding: 0 12px;
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-radius-sm);
	background: var(--ps-bg);
	color: var(--ps-ink);
	font-size: var(--ps-text-sm);
	font-weight: 600;
	text-decoration: none;
}

.ps-pagination__item .page-numbers:hover {
	border-color: var(--ps-accent);
	color: var(--ps-accent);
}

.ps-pagination__item .current {
	background: var(--ps-accent);
	border-color: var(--ps-accent);
	color: var(--ps-accent-ink);
}

/* ==========================================================================
   18. EMPTY / 404 / NOTICES
   ========================================================================== */

.ps-empty,
.ps-404 {
	max-width: 640px;
	margin: 0 auto;
	padding: var(--ps-gap-xl) 0;
	text-align: center;
}

.ps-404__code {
	margin: 0;
	font-size: 5rem;
	font-weight: 800;
	line-height: 1;
	color: var(--ps-accent-soft);
	letter-spacing: -0.04em;
}

.ps-empty__title,
.ps-404__title {
	margin: 0 0 var(--ps-gap-sm);
	font-size: var(--ps-text-2xl);
}

.ps-empty__text,
.ps-404__text {
	margin: 0 0 var(--ps-gap);
	color: var(--ps-muted);
}

.ps-empty__search,
.ps-404__search {
	display: flex;
	justify-content: center;
	margin-bottom: var(--ps-gap);
}

.ps-empty__actions,
.ps-404__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--ps-gap-sm);
}

.ps-404__suggestions {
	margin-top: var(--ps-gap-xl);
	padding-top: var(--ps-gap-lg);
	border-top: 1px solid var(--ps-line);
}

.ps-notice {
	padding: var(--ps-gap);
	border: 1px solid var(--ps-line);
	border-left: 4px solid var(--ps-accent);
	border-radius: var(--ps-radius);
	background: var(--ps-surface);
}

.ps-notice__title {
	margin: 0 0 6px;
	font-size: var(--ps-text-lg);
}

.ps-notice__text {
	margin: 0;
	color: var(--ps-muted);
}

/* ==========================================================================
   19. FOOTER
   ========================================================================== */

.ps-footer {
	margin-top: auto;
	background: var(--ps-inverse);
	color: var(--ps-on-inverse);
}

.ps-footer__inner {
	max-width: var(--ps-container);
	margin: 0 auto;
	padding: 0 var(--ps-gutter);
}

.ps-footer__top {
	padding: var(--ps-gap-xl) 0 var(--ps-gap-lg);
}

.ps-footer__top .ps-footer__inner {
	display: grid;
	/* Brand column carries the lockup, the about copy, the social row and the
	   contact list - more to hold than the widget column beside it. */
	grid-template-columns: minmax(0, 1.5fr) minmax(0, 2fr);
	gap: var(--ps-gap-lg);
}

/* Brand block: the lockup gets a row of its own, then About and Contact share
   the row beneath it. Both collapse to a single column when there is no room. */
.ps-footer__mark {
	margin-bottom: var(--ps-gap);
	padding-bottom: var(--ps-gap);
	border-bottom: 1px solid var(--ps-line);
}

.ps-footer__split {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--ps-gap);
}

/* Only split once there is genuinely width for two readable columns. */
@media (min-width: 900px) {
	.ps-footer__split {
		grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
		gap: var(--ps-gap-lg);
	}
}

.ps-footer__col {
	min-width: 0;
}

.ps-footer__col--contact .ps-footer__contact {
	margin-bottom: 0;
}

.ps-footer__brand .ps-brand__name,
.ps-footer__brand .ps-brand__link {
	color: #fff;
}

.ps-footer__brand .ps-brand__tagline {
	color: var(--ps-on-inverse);
}

.ps-footer__about {
	margin: 0 0 var(--ps-gap);
	font-size: var(--ps-text-sm);
	line-height: var(--ps-leading);
	color: var(--ps-on-inverse);
	max-width: 46ch;
}

.ps-footer__contact {
	display: grid;
	gap: 6px;
	margin: 0 0 var(--ps-gap);
	padding: 0;
	list-style: none;
}

.ps-footer__contact-item {
	font-size: var(--ps-text-sm);
	color: var(--ps-on-inverse);
}

.ps-footer__contact-item--address {
	line-height: 1.5;
	color: rgba(226, 232, 240, 0.8);
}

.ps-footer__contact-item--hours {
	color: rgba(226, 232, 240, 0.8);
}

.ps-footer__contact-link {
	color: #fff;
	font-weight: 600;
	text-decoration: none;
}

.ps-footer__contact-link:hover {
	text-decoration: underline;
	color: #fff;
}

.ps-footer__social {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ps-footer__social-link {
	display: inline-block;
	padding: 6px 14px;
	border: 1px solid rgba(255, 255, 255, 0.2);
	border-radius: var(--ps-radius-pill);
	color: #fff;
	font-size: var(--ps-text-xs);
	font-weight: 600;
	text-decoration: none;
}

.ps-footer__social-link:hover {
	border-color: #fff;
	background: rgba(255, 255, 255, 0.08);
	color: #fff;
}

.ps-footer__widgets {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--ps-gap-lg);
}

.ps-footer__widget-title {
	margin: 0 0 var(--ps-gap-sm);
	font-size: var(--ps-text-xs);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #fff;
}

.ps-footer__widget ul,
.ps-footer__menu {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 8px;
}

.ps-footer__widget a,
.ps-footer__menu a {
	color: var(--ps-on-inverse);
	font-size: var(--ps-text-sm);
	text-decoration: none;
}

.ps-footer__widget a:hover,
.ps-footer__menu a:hover {
	color: #fff;
	text-decoration: underline;
}

.ps-footer__payments-row {
	padding: var(--ps-gap) 0;
	border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.ps-footer__payments {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
}

.ps-footer__payments-label {
	font-size: var(--ps-text-xs);
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ps-on-inverse);
}

.ps-footer__payment {
	padding: 5px 12px;
	border: 1px solid rgba(255, 255, 255, 0.2);
	border-radius: var(--ps-radius-sm);
	font-size: var(--ps-text-xs);
	font-weight: 600;
	color: #fff;
}

.ps-footer__legal {
	padding: var(--ps-gap) 0 var(--ps-gap-lg);
	border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.ps-footer__disclaimer {
	margin: 0 0 var(--ps-gap);
	font-size: var(--ps-text-xs);
	line-height: 1.7;
	color: rgba(226, 232, 240, 0.75);
}

.ps-footer__bottom {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--ps-gap-sm);
}

.ps-footer__copyright {
	margin: 0;
	font-size: var(--ps-text-xs);
	color: var(--ps-on-inverse);
}

.ps-footer__legal-menu {
	display: flex;
	flex-wrap: wrap;
	gap: var(--ps-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

.ps-footer__legal-menu a {
	font-size: var(--ps-text-xs);
	color: var(--ps-on-inverse);
	text-decoration: none;
}

.ps-footer__legal-menu a:hover {
	color: #fff;
	text-decoration: underline;
}

/* ==========================================================================
   20. AGE GATE
   ========================================================================== */

.ps-age-gate {
	position: fixed;
	inset: 0;
	z-index: var(--ps-z-gate);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--ps-gutter);
	background: rgba(11, 26, 43, 0.85);
}

.ps-age-gate[hidden] {
	display: none;
}

.ps-age-gate__dialog {
	width: 100%;
	max-width: 560px;
	/* Two statements and a note can outgrow a phone screen; the dialog scrolls
	   rather than pushing the buttons out of reach. */
	max-height: calc(100vh - 2 * var(--ps-gutter));
	max-height: calc(100dvh - 2 * var(--ps-gutter));
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: var(--ps-gap-lg);
	border-radius: var(--ps-panel-radius);
	/* Solid base first, gradient on top: the gate sits over an unknown page, so
	   it cannot rely on what is behind it for contrast. */
	background-color: var(--ps-bg);
	background-image: linear-gradient(
		var(--ps-panel-angle),
		var(--ps-panel-a) 0%,
		var(--ps-panel-b) 100%
	);
	color: var(--ps-panel-ink);
	box-shadow: var(--ps-shadow-lg);
	text-align: center;
}

.ps-age-gate__eyebrow {
	margin: 0 0 6px;
	font-size: var(--ps-text-xs);
	font-weight: 650;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ps-accent);
}

.ps-age-gate__title {
	margin: 0 0 var(--ps-gap-sm);
	font-size: var(--ps-text-xl);
}

.ps-age-gate__text {
	margin: 0 0 var(--ps-gap);
	font-size: var(--ps-text-sm);
	line-height: var(--ps-leading);
	color: var(--ps-panel-ink-soft);
}

/* The statements read as running text, so they sit left-aligned inside the
   otherwise centred dialog. */
.ps-age-gate__checks {
	display: flex;
	flex-direction: column;
	gap: var(--ps-gap-sm);
	margin: 0 0 var(--ps-gap);
	text-align: left;
}

.ps-age-gate__check {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	padding: 12px 14px;
	border: 1px solid rgba(127, 127, 127, 0.35);
	border-radius: var(--ps-radius-sm);
	font-size: var(--ps-text-sm);
	line-height: var(--ps-leading);
	cursor: pointer;
}

.ps-age-gate__check:has(.ps-age-gate__radio:checked) {
	border-color: var(--ps-accent);
}

.ps-age-gate__radio {
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	margin: 2px 0 0;
	accent-color: var(--ps-accent);
	cursor: pointer;
}

.ps-age-gate__check-text {
	flex: 1 1 auto;
	min-width: 0;
}

.ps-age-gate__check-lead {
	display: block;
	margin-bottom: 4px;
	font-weight: 650;
}

.ps-age-gate__link {
	color: inherit;
	text-decoration: underline;
}

.ps-age-gate__actions {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--ps-gap-sm);
}

.ps-age-gate__accept[disabled] {
	opacity: 0.45;
	cursor: not-allowed;
}

.ps-age-gate__decline {
	font-size: var(--ps-text-xs);
	color: var(--ps-muted);
}

.ps-age-gate__legal {
	margin: var(--ps-gap) 0 0;
	font-size: var(--ps-text-xs);
	line-height: var(--ps-leading);
	color: var(--ps-panel-ink-soft);
}

.ps-body--gated {
	overflow: hidden;
}

/* ==========================================================================
   21. ACCESSIBILITY
   ========================================================================== */

.ps-skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: calc(var(--ps-z-gate) + 1);
	padding: 12px 20px;
	background: var(--ps-accent);
	color: var(--ps-accent-ink);
	font-weight: 650;
	text-decoration: none;
}

.ps-skip-link:focus {
	left: 8px;
	top: 8px;
	color: var(--ps-accent-ink);
}

.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.screen-reader-text:focus {
	position: static !important;
	width: auto;
	height: auto;
	clip: auto;
	margin: 0;
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	.ps-nav,
	.ps-search-form {
		transition: none;
	}

	.ps-header__inner,
	.ps-brand__image,
	.ps-brand__contact {
		transition: none;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
	}
}

/* ==========================================================================
   22. RESPONSIVE
   ========================================================================== */

@media (max-width: 1100px) {

		.ps-header__toggle {
		display: inline-flex;
		order: 2;
	}
	.ps-archive__grid,
	.ps-search__grid {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.ps-layout--sidebar {
		grid-template-columns: minmax(0, 1fr);
	}
	/* The stage: pinned under the header bar and out of the flow, so whatever
	   the panel inside it does to its own height, the document's height does not
	   move and the page cannot jump. This is what the panel is measured against
	   now, instead of the flex row it used to sit in. */
	/* The panel drops from the notice down across the header, which puts it
	   straight over the button that opened it - leaving nothing to click to
	   shut it again. Lift the toggle above the panel so it stays reachable the
	   whole time the menu is down. */
	.ps-header__toggle {
		position: relative;
		z-index: var(--ps-z-header);
	}

	.ps-nav-stage {
		display: block;
		position: absolute;
		top: 100%;
		left: 0;
		right: 0;
		z-index: calc(var(--ps-z-header) - 1);
	}

	/* The panel hangs from the pinned notice and drops down over the page. It
	   did sit in the header and push everything below it, which meant opening it
	   at the top of the page had to scroll the page to bring it into view - the
	   jarring part. Hanging it here is also what the compact bar does further
	   down (that rule only changes `top`), so the menu behaves identically at
	   every scroll position: same anchor, same top-down drop.

	   Collapsed with max-height rather than display, because display is a
	   discrete property and cannot be transitioned - toggling it snaps the panel
	   in and out with no animation at all. visibility is held until the close
	   has finished so the links leave the tab order without cutting the fade. */
	.ps-nav {
		position: fixed;
		top: var(--ps-announce-height, 0px);
		left: 0;
		right: 0;
		z-index: calc(var(--ps-z-header) - 1);
		width: auto;
		max-height: 0;
		overflow: hidden;
		opacity: 0;
		visibility: hidden;
		background: #050706;
		transition: max-height 0.28s ease, opacity 0.2s ease,
			visibility 0s linear 0.28s;
	}

	.ps-nav.is-open {
		/* 100% works here because the panel is positioned - it resolves against
		   the viewport rather than the auto-height flex row it used to sit in. */
		max-height: 100%;
		opacity: 1;
		visibility: visible;
		overflow-y: auto;
		border-bottom: 1px solid var(--ps-line);
		box-shadow: 0 12px 30px rgba(0, 0, 0, 0.6);
		transition: max-height 0.32s ease, opacity 0.24s ease, visibility 0s;
	}

	/* Padding on the list, not the panel - see the compact-bar rules. */
	.ps-nav .ps-nav__list {
		flex-direction: column;
		align-items: stretch;
		justify-content: flex-start;
		max-width: var(--ps-container);
		margin: 0 auto;
		padding: 0 var(--ps-gutter) var(--ps-gap);
	}

	.ps-nav__list {
		flex-direction: column;
		align-items: stretch;
		gap: 2px;
		padding: var(--ps-gap-sm) 0;
		border-top: 1px solid var(--ps-line);
	}

	.ps-nav__list .sub-menu {
		position: static;
		opacity: 1;
		visibility: visible;
		transform: none;
		box-shadow: none;
		border: 0;
		padding-left: var(--ps-gap);
	}

}

@media (max-width: 900px) {
	.ps-header__inner {
		flex-wrap: wrap;
	}



	.ps-header__actions {
		order: 3;
		width: 100%;
		justify-content: space-between;
	}


	.ps-hero--has-image .ps-hero__inner {
		grid-template-columns: minmax(0, 1fr);
	}

	/* 70% of a phone viewport is far too narrow to read in, so the hero panel
	   widens and the tall min-height relaxes. */
	.ps-hero__inner {
		width: calc(100% - (var(--ps-gutter) * 2));
		min-height: 0;
		margin: var(--ps-gutter) auto;
	}

	.ps-hero__heading {
		font-size: var(--ps-text-3xl);
	}

	.ps-product__top {
		grid-template-columns: minmax(0, 1fr);
	}

	.ps-purchase {
		position: static;
	}

	.ps-trust__list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.ps-footer__top .ps-footer__inner {
		grid-template-columns: minmax(0, 1fr);
	}

	.ps-archive__header--has-image {
		grid-template-columns: minmax(0, 1fr);
	}

	.ps-search-form {
		max-width: none;
		flex: 1 1 auto;
	}
}

@media (max-width: 782px) {
	.ps-archive__grid,
	.ps-search__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.ps-footer__widgets {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.ps-post--summary {
		grid-template-columns: minmax(0, 1fr);
	}

	.ps-shell {
		padding-top: var(--ps-gap);
		padding-bottom: var(--ps-gap-lg);
	}

	.ps-section {
		padding: var(--ps-gap-lg) 0;
	}
}

@media (max-width: 560px) {
	:root {
		--ps-text-3xl: 1.75rem;
		--ps-text-4xl: 2.125rem;
		--ps-gutter: 16px;
	}

	.ps-archive__grid,
	.ps-search__grid {
		grid-template-columns: minmax(0, 1fr);
	}

	.ps-trust__list {
		grid-template-columns: minmax(0, 1fr);
	}

	.ps-footer__widgets {
		grid-template-columns: minmax(0, 1fr);
	}

	.ps-topbar__inner {
		flex-direction: column;
		align-items: flex-start;
	}

	.ps-cta {
		padding: var(--ps-gap);
	}

	.ps-header__cta {
		display: none;
	}
}

/* The search field and the cart pill both have a hard minimum width - the
   field needs room to type in, and the pill is nowrap - and under about 480px
   they no longer both fit on one line, so the row overflows. Drop the cart to
   its own full-width row beneath the search. Each control keeps its own
   horizontal layout; only their relationship to each other stacks. */
@media (max-width: 480px) {
	.ps-header__actions {
		flex-wrap: wrap;
		gap: var(--ps-gap-sm);
	}

	/* The field is folded away behind the icon button, which frees the row for
	   the cart. Opening it drops the full form onto its own line rather than
	   squeezing it in beside the button, so the input keeps a usable width. */
	.ps-search-toggle {
		display: inline-flex;
	}

	.ps-search-form {
		flex: 1 1 100%;
		order: 3;
		max-height: 0;
		margin-top: calc(var(--ps-gap-sm) * -1);
		overflow: hidden;
		opacity: 0;
		visibility: hidden;
		transition: max-height 0.24s ease, margin-top 0.24s ease,
			opacity 0.18s ease, visibility 0s linear 0.24s;
	}

	/* Revealed: the whole bar - field plus its Search button - spans the
	   viewport. The magnifier is a separate control and is not included. */
	.ps-header__actions.is-search-open .ps-search-form {
		width: 100%;
		max-width: 100%;
		max-height: 100%;
		margin-top: 0;
		opacity: 1;
		visibility: visible;
		transition: max-height 0.26s ease, margin-top 0.26s ease,
			opacity 0.2s ease, visibility 0s;
	}

	/* Collapsed, the icon and the cart share one row - the cart takes the rest
	   of it. Revealing the field pushes only the field onto a line of its own
	   (it is ordered last), so this pair stays put either way. */
	.ps-header__actions .pc-cart-link {
		flex: 1 1 auto;
		width: auto;
		justify-content: center;
	}
}
