/* edd-blocks */
:root {
	--edd-blocks-light-grey: #eee;
}

.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	-webkit-clip-path: inset(50%);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal !important;
}


/* contact-form-7 */
.wpcf7 .screen-reader-response {
	position: absolute;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	width: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	word-wrap: normal !important;
	word-break: normal !important;
}

.wpcf7 .hidden-fields-container {
	display: none;
}

.wpcf7 form .wpcf7-response-output {
	margin: 2em 0.5em 1em;
	padding: 0.2em 1em;
	border: 2px solid #00a0d2; /* Blue */
}

.wpcf7 form.init .wpcf7-response-output,
.wpcf7 form.resetting .wpcf7-response-output,
.wpcf7 form.submitting .wpcf7-response-output {
	display: none;
}

.wpcf7 form.sent .wpcf7-response-output {
	border-color: #46b450; /* Green */
}

.wpcf7 form.failed .wpcf7-response-output,
.wpcf7 form.aborted .wpcf7-response-output {
	border-color: #dc3232; /* Red */
}

.wpcf7 form.spam .wpcf7-response-output {
	border-color: #f56e28; /* Orange */
}

.wpcf7 form.invalid .wpcf7-response-output,
.wpcf7 form.unaccepted .wpcf7-response-output,
.wpcf7 form.payment-required .wpcf7-response-output {
	border-color: #ffb900; /* Yellow */
}

.wpcf7-form-control-wrap {
	position: relative;
}

.wpcf7-not-valid-tip {
	color: #dc3232; /* Red */
	font-size: 1em;
	font-weight: normal;
	display: block;
}

.use-floating-validation-tip .wpcf7-not-valid-tip {
	position: relative;
	top: -2ex;
	left: 1em;
	z-index: 100;
	border: 1px solid #dc3232;
	background: #fff;
	padding: .2em .8em;
	width: 24em;
}

.wpcf7-list-item {
	display: inline-block;
	margin: 0 0 0 1em;
}

.wpcf7-list-item-label::before,
.wpcf7-list-item-label::after {
	content: " ";
}

.wpcf7-spinner {
	visibility: hidden;
	display: inline-block;
	background-color: #23282d; /* Dark Gray 800 */
	opacity: 0.75;
	width: 24px;
	height: 24px;
	border: none;
	border-radius: 100%;
	padding: 0;
	margin: 0 24px;
	position: relative;
}

form.submitting .wpcf7-spinner {
	visibility: visible;
}

.wpcf7-spinner::before {
	content: '';
	position: absolute;
	background-color: #fbfbfc; /* Light Gray 100 */
	top: 4px;
	left: 4px;
	width: 6px;
	height: 6px;
	border: none;
	border-radius: 100%;
	transform-origin: 8px 8px;
	animation-name: spin;
	animation-duration: 1000ms;
	animation-timing-function: linear;
	animation-iteration-count: infinite;
}

@media (prefers-reduced-motion: reduce) {
	.wpcf7-spinner::before {
		animation-name: blink;
		animation-duration: 2000ms;
	}
}

@keyframes spin {
	from {
		transform: rotate(0deg);
	}

	to {
		transform: rotate(360deg);
	}
}

@keyframes blink {
	from {
		opacity: 0;
	}

	50% {
		opacity: 1;
	}

	to {
		opacity: 0;
	}
}

.wpcf7 [inert] {
	opacity: 0.5;
}

.wpcf7 input[type="file"] {
	cursor: pointer;
}

.wpcf7 input[type="file"]:disabled {
	cursor: default;
}

.wpcf7 .wpcf7-submit:disabled {
	cursor: not-allowed;
}

.wpcf7 input[type="url"],
.wpcf7 input[type="email"],
.wpcf7 input[type="tel"] {
	direction: ltr;
}

.wpcf7-reflection > output {
	display: list-item;
	list-style: none;
}

.wpcf7-reflection > output[hidden] {
	display: none;
}


/* edd_all_access_css */
#edd-aa-login-modal-content #edd_login_form{margin-top:0}#edd-aa-login-modal-content #edd_login_form fieldset{margin-bottom:0}.edd-aa-login-purchase-normal-plus-aa-mode{margin-top:20px}#edd-aa-login-modal-content .edd-lost-password{margin-bottom:0!important}.edd-aa-buy-btns-wrapper>div:nth-child(n+2){margin-top:5px}.edd-aa-buy-instructions{display:block;margin-bottom:5px}.edd-aa-login-wrapper{margin-top:5px}.edd-aa-upcoming-end-date,.edd-aa-upcoming-start-date{display:block}

/* edd-multi-currency */
.edd-multi-currency-selector-buttons form{display:flex;flex-wrap:wrap;gap:5px}.edd-multi-currency-button--selected{opacity:.6}


/* puregpl-main-page */
/**
 * PureGPL — homepage.
 *
 * Continues the header's Aurora surface through the whole page and out into the
 * footer. There is no light band anywhere, so there is no seam to get wrong:
 * the page reads as one object rather than three stacked ones.
 *
 * Tokens come from chrome.css, which is always enqueued before this file. The
 * few defined here are homepage-specific.
 */

/*
 * GeneratePress paints the body rgb(247,248,249). The dark sections cover most
 * of it, but it shows through anywhere they do not reach — above the header on
 * a rubber-band scroll, and in the gap below the footer on a short viewport —
 * as a light band that breaks the illusion of one continuous surface.
 *
 * Scoped to .home so every other page keeps its light background.
 */
/*
 * The page is LIGHT, between dark chrome.
 *
 * A near-black page hid the one thing this store sells: product screenshots.
 * Theme art is bright, colourful and detailed, and on a dark ground every tile
 * became a glowing rectangle competing with its neighbours. On white the art
 * supplies the colour and the interface stays quiet — which is how every
 * marketplace worth copying handles a catalogue of visual products.
 *
 * Dark header and footer bracketing a light body is deliberate, not a
 * compromise: the chrome reads as the frame, the page as the merchandise.
 */
body.home {
	background-color: #fff;
}

.ph {
	/*
	 * A real system, imposed late.
	 *
	 * Before this the page carried 24 distinct size/weight pairs and 13 different
	 * corner radii — 4px, 5.6px, 9px, 10.368px, 13px, 26px and so on — because
	 * every section had been designed on its own and invented its own values.
	 * That is what reads as "basic" no matter how well any single section is
	 * drawn: nothing rhymes with anything else.
	 *
	 * Two families, one scale, four radii.
	 */

	/*
	 * Bricolage Grotesque was already being loaded by the site chrome and never
	 * used here — every heading rendered in Poppins, which is the most-used
	 * geometric sans on the web and the closest thing to a default a page can
	 * have. Bricolage has real character in its wide, slightly odd caps, and it
	 * costs nothing extra because the font is already on the wire.
	 */
	--ph-display: "Bricolage Grotesque", "Poppins", system-ui, sans-serif;

	/*
	 * A modular scale, not twenty-four guesses.
	 *
	 * Sized so BODY copy lands at 16px. The first pass put it on --t-sm and it
	 * rendered at 13.6px — which was the original complaint, just expressed
	 * through a token. Small body copy is the most reliable way to make a page
	 * feel cheap: it reads as "we had a lot to fit in" rather than "we chose
	 * what mattered".
	 */
	--t-3xl: clamp(2.5rem, 5.2vw, 4.2rem);
	--t-2xl: clamp(1.85rem, 3.4vw, 2.7rem);
	--t-xl: clamp(1.3rem, 2vw, 1.6rem);
	--t-lg: 1.15rem;
	--t-md: 1rem;
	--t-sm: 0.925rem;
	--t-xs: 0.8rem;

	/* Four radii. Sharp for chips, soft for panels, round for pills. */
	--r-sm: 10px;
	--r-md: 16px;
	--r-lg: 22px;
	--r-full: 999px;

	--ph-bg: #ffffff;
	/* A tint carrying a trace of the accent, so it never reads as flat grey. */
	--ph-tint: #f6f7fd;
	--ph-panel: #ffffff;
	--ph-line: rgba(11, 14, 28, 0.09);
	--ph-line-2: rgba(11, 14, 28, 0.06);
	--ph-ink: #0b0e1c;
	--ph-mute: #55607d;
	/*
	 * #8791a8 measured 3.16:1 on white — below AA for the small text this token
	 * carries (category counts, eyebrows, stat labels, brand counts). Darkened
	 * until every one of them passes; still clearly secondary to --ph-mute.
	 */
	--ph-mute-2: #66708b;
	--ph-live: #16a34a;

	position: relative;
	color: var(--ph-mute);
	background: var(--ph-bg);
	font-size: var(--t-lg);
	line-height: 1.6;
}

.ph-wrap {
	max-width: 1240px;
	margin: 0 auto;
	padding: 0 max(1rem, env(safe-area-inset-left));
}

/* GeneratePress wraps the page in a container that would fight this layout. */
.home .site-content,
.home .content-area,
.home .site-main {
	max-width: none;
	margin: 0;
	padding: 0;
}

.home .site-content {
	display: block;
}

/* --- Buttons -------------------------------------------------------------- */

.ph .ph-btn {
	display: inline-flex;
	gap: 0.5rem;
	align-items: center;
	justify-content: center;
	padding: 0.85rem 1.6rem;
	color: #fff;
	font-size: var(--t-md);
	font-weight: 700;
	text-decoration: none;
	border-radius: 999px;
	transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}

/*
 * The transparent border is load-bearing: --ghost carries a real 1px border, so
 * without a matching one here the two buttons differ by 2px in height and sit
 * on different baselines wherever they appear side by side.
 */
.ph .ph-btn--solid {
	background: var(--pgpl-ultra);
	border: 1px solid transparent;
	box-shadow: 0 16px 34px -16px rgba(60, 80, 255, 0.95);
}

.ph .ph-btn--ghost {
	color: var(--ph-ink);
	background: #fff;
	border: 1px solid rgba(11, 14, 28, 0.14);
}

@media (hover: hover) and (pointer: fine) {
	.ph .ph-btn--solid:hover { background: var(--pgpl-ultra-deep); transform: translateY(-1px); }
	.ph .ph-btn--ghost:hover { background: var(--ph-tint); border-color: rgba(11, 14, 28, 0.24); }
}

.ph .ph-btn svg { transition: transform 0.15s ease; }
.ph .ph-btn:hover svg { transform: translateX(2px); }

/* --- Hero ----------------------------------------------------------------- */

.ph-hero {
	position: relative;
	overflow: hidden;
	padding: clamp(1.6rem, 3vw, 2.6rem) 0 clamp(1.6rem, 3vw, 2.4rem);
}

/*
 * A fine dot grid, static, faded out where the copy sits. The cheapest way to
 * make a large area read as a considered surface rather than as blank space.
 */
.ph-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	background-image: radial-gradient(circle, rgba(11, 14, 28, 0.13) 1px, transparent 1px);
	background-size: 26px 26px;
	-webkit-mask-image: radial-gradient(ellipse 60% 55% at 26% 40%, transparent 26%, #000 76%);
	mask-image: radial-gradient(ellipse 60% 55% at 26% 40%, transparent 26%, #000 76%);
	opacity: 0.75;
	pointer-events: none;
}

/* --- Aurora --------------------------------------------------------------- */

/*
 * Three colour fields drifting on long, deliberately unequal cycles. Every one
 * animates TRANSFORM only, so the browser composites them on the GPU and the
 * main thread does nothing per frame. Animating a filter or a gradient stop
 * instead forces a repaint every frame — the difference between atmosphere and
 * a hero that stutters while the page is still loading.
 */
.ph-aurora {
	position: absolute;
	inset: -20% -10% auto -10%;
	height: 130%;
	overflow: hidden;
	pointer-events: none;
}

.ph-aurora span {
	position: absolute;
	display: block;
	border-radius: 50%;
	will-change: transform;
}

.ph-aurora__a {
	top: -12%;
	left: 2%;
	width: 44vw;
	height: 44vw;
	max-width: 700px;
	max-height: 700px;
	background: radial-gradient(circle at 50% 50%, rgba(108, 134, 255, 0.42), transparent 66%);
	animation: ph-float-a 34s ease-in-out infinite;
}

.ph-aurora__b {
	top: 4%;
	right: 2%;
	width: 40vw;
	height: 40vw;
	max-width: 640px;
	max-height: 640px;
	background: radial-gradient(circle at 50% 50%, rgba(0, 182, 122, 0.22), transparent 66%);
	animation: ph-float-b 43s ease-in-out infinite;
}

.ph-aurora__c {
	top: 34%;
	left: 30%;
	width: 34vw;
	height: 34vw;
	max-width: 560px;
	max-height: 560px;
	background: radial-gradient(circle at 50% 50%, rgba(168, 120, 255, 0.3), transparent 66%);
	animation: ph-float-c 51s ease-in-out infinite;
}

@keyframes ph-float-a {
	0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
	50%      { transform: translate3d(9%, 7%, 0) scale(1.14); }
}

@keyframes ph-float-b {
	0%, 100% { transform: translate3d(0, 0, 0) scale(1.06); }
	50%      { transform: translate3d(-11%, 9%, 0) scale(0.92); }
}

@keyframes ph-float-c {
	0%, 100% { transform: translate3d(0, 0, 0) scale(0.95); }
	50%      { transform: translate3d(7%, -8%, 0) scale(1.12); }
}

/* --- Split layout --------------------------------------------------------- */

.ph-hero__grid {
	position: relative;
	z-index: 2;
	display: grid;
	grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
	gap: clamp(1.2rem, 3vw, 2.4rem);
	align-items: center;
	min-height: 0;
}

.ph-hero__copy { min-width: 0; }

.ph-hero__title {
	font-family: var(--ph-display);
	margin: 0;
	color: var(--ph-ink);
	font-size: clamp(2.2rem, 4.6vw, 3.6rem);
	font-weight: 800;
	line-height: 1;
	letter-spacing: -0.04em;
}

.ph-hero__title span { display: block; }

/*
 * Line two steps back so line one and the price both come forward. A headline
 * set at one flat weight reads as a wall of text however large it is; the whole
 * job of a display size is to create a hierarchy inside itself.
 */
.ph-hero__l2 { color: rgba(11, 14, 28, 0.62); }

/*
 * The tag is taller than the line box it sits in — padding pushes it past the
 * text baseline — so at line-height 1 its top edge ran into the descender of
 * "plugins" above. This buys the clearance back.
 */
.ph-hero__l3 {
	display: flex !important;
	gap: 0.4em;
	align-items: center;
	margin-top: 0.24em;
}

.ph-hero__from {
	display: inline !important;
	color: rgba(11, 14, 28, 0.62);
}

/*
 * The price as a shop tag.
 *
 * Written inline it was the sentence continuing in a different colour — the
 * most important fact on the page carried by nothing but a hue change. A tag is
 * the object a price belongs on, and on a store whose entire argument is cost,
 * that is the detail worth spending craft on.
 *
 * The tilt is 1.5deg. Enough to read as a physical thing pinned to the page;
 * more and it looks like a mistake.
 */
.ph-hero__tag {
	font-family: var(--ph-display);
	display: inline-flex !important;
	position: relative;
	align-items: center;
	padding: 0.07em 0.4em 0.07em 0.55em;
	color: #fff;
	background: linear-gradient(135deg, var(--pgpl-ultra), #5b32e8);
	border-radius: 0.18em;
	box-shadow:
		0 10px 24px -10px rgba(60, 80, 255, 0.75),
		inset 0 1px 0 rgba(255, 255, 255, 0.25);
	transform: rotate(-1.5deg);
}

/* The punch-hole, which is what makes it read as a tag rather than a button. */
.ph-hero__tag-hole {
	width: 0.13em;
	height: 0.13em;
	margin-right: 0.28em;
	background: rgba(255, 255, 255, 0.45);
	border-radius: 50%;
	box-shadow: inset 0 0.02em 0.03em rgba(11, 14, 28, 0.5);
}

.ph-hero__lede {
	max-width: 44ch;
	margin: 1.15rem 0 0;
	color: var(--ph-mute);
	font-size: clamp(0.98rem, 1.2vw, 1.06rem);
	text-wrap: pretty;
}

.ph-hero__cta {
	display: flex;
	gap: 0.6rem;
	align-items: center;
	flex-wrap: wrap;
	margin-top: 1.5rem;
}

/* --- Guarantees ----------------------------------------------------------- */

/*
 * Three facts the store can stand behind, in place of a review count. Each
 * answers an objection a GPL buyer actually arrives with — will I get it now,
 * can I use it on client sites, has it been tampered with.
 */
.ph-hero__promises {
	display: flex;
	gap: 1.1rem;
	flex-wrap: wrap;
	margin: 1.5rem 0 0;
	padding: 0;
	list-style: none;
}

.ph-hero__promises li {
	display: flex;
	gap: 0.4rem;
	align-items: center;
	color: var(--ph-mute);
	font-size: var(--t-xs);
	font-weight: 600;
}

.ph-hero__promises svg { color: #16a34a; flex: 0 0 auto; }

/* --- Entrance ------------------------------------------------------------- */

/*
 * A short staggered rise, once, on load. Pure CSS with per-element delays —
 * no observer, no script. Only transform and opacity animate, so the whole
 * sequence runs on the compositor and cannot delay anything else rendering.
 */
.ph-hero__l1,
.ph-hero__l2,
.ph-hero__l3,
.ph-hero__lede,
.ph-hero__cta,
.ph-hero__promises {
	animation: ph-rise 0.7s cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

.ph-hero__l1        { animation-delay: 0.06s; }
.ph-hero__l2        { animation-delay: 0.13s; }
.ph-hero__l3        { animation-delay: 0.2s; }
.ph-hero__lede      { animation-delay: 0.28s; }
.ph-hero__cta       { animation-delay: 0.36s; }
.ph-hero__promises  { animation-delay: 0.44s; }

@keyframes ph-rise {
	from { opacity: 0; transform: translateY(14px); }
	to   { opacity: 1; transform: translateY(0); }
}

/* --- The product wall ----------------------------------------------------- */

/*
 * Three columns of real catalogue artwork, tilted into perspective and drifting
 * vertically at different speeds in alternating directions.
 *
 * This is the piece the hero was missing. A store selling things people buy
 * with their eyes was showing brand logos and no products; a wall of actual
 * screenshots proves the inventory in the first screen instead of describing
 * it, and the depth is what stops it reading as a plain grid.
 */
.ph-wall {
	position: relative;
	height: clamp(27rem, 46vw, 38rem);
	/*
	 * Load-bearing. Each column stacks twelve tiles and is far taller than the
	 * frame by design — that overflow is what there is to scroll. Without this
	 * the columns expand the grid instead, and the hero grows to 5,297px.
	 */
	overflow: hidden;
	/* The vanishing point sits left, so the wall recedes toward the copy. */
	perspective: 1400px;
	perspective-origin: 10% 50%;
	/* A shallower fade than before, so more of the wall is legible. */
	-webkit-mask-image: linear-gradient(180deg, transparent, #000 7%, #000 92%, transparent);
	mask-image: linear-gradient(180deg, transparent, #000 7%, #000 92%, transparent);
}

.ph-wall__stage {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: 0.45rem;
	height: 100%;
	/*
	 * scale(1.2) was slicing the outer columns off.
	 *
	 * rotateY already widens the stage's horizontal footprint — the near edge
	 * swings toward the viewer — and scaling up on top of that pushed both outer
	 * columns past the clip, slicing the left and right logos in half.
	 *
	 * Scaling DOWN to 0.86 fits the whole stage inside the frame, and the density
	 * that the old scale was buying comes back from a fifth column of smaller
	 * tiles. The translateX corrects the offset the rotation leaves behind:
	 * without it the stage sits 37px from the left edge and 4px from the right.
	 */
	transform: rotateY(-14deg) rotateX(4deg) rotateZ(-1.5deg) scale(0.86) translateX(-4.8%);
	transform-style: preserve-3d;
}

.ph-wall__col {
	display: flex;
	flex-direction: column;
	gap: 0.45rem;
	will-change: transform;
}

/*
 * Alternating directions and unequal durations. Matched, the three columns
 * would slide as one sheet; opposed, the wall reads as depth.
 */
.ph-wall__col--0 { animation: ph-wall-up 46s linear infinite; }
.ph-wall__col--1 { animation: ph-wall-down 58s linear infinite; }
.ph-wall__col--2 { animation: ph-wall-up 52s linear infinite; }
.ph-wall__col--3 { animation: ph-wall-down 64s linear infinite; }
.ph-wall__col--4 { animation: ph-wall-up 57s linear infinite; }

/* Each column holds its tiles twice, so 50% lands on an identical frame. */
@keyframes ph-wall-up {
	from { transform: translate3d(0, 0, 0); }
	to   { transform: translate3d(0, -50%, 0); }
}

@keyframes ph-wall-down {
	from { transform: translate3d(0, -50%, 0); }
	to   { transform: translate3d(0, 0, 0); }
}

/*
 * Square plates now, holding brand marks rather than product screenshots.
 *
 * object-fit: contain, not cover — the set mixes portrait cards with square
 * avatars, and cover sliced the ends off the wide ones. A brand wall that crops
 * brand names is worse than no brand wall.
 */
/*
 * Edge to edge, no padding.
 *
 * These logos are not transparent marks needing a card behind them — each one
 * is already a finished plate with its own background and its own margins baked
 * in. Framing them in white added a second border around a border, and the wall
 * read as a grid of frames rather than a grid of brands.
 */
.ph-wall__tile {
	display: block;
	flex: 0 0 auto;
	aspect-ratio: 1;
	overflow: hidden;
	background: var(--ph-tint);
	border-radius: var(--r-sm);
	box-shadow:
		0 0 0 1px rgba(11, 14, 28, 0.06),
		0 14px 26px -18px rgba(11, 14, 28, 0.45);
}

/*
 * cover, not contain. The set is overwhelmingly square, so cover fills the tile
 * with almost nothing lost; contain would letterbox the few portrait plates and
 * reintroduce exactly the empty margins this removes.
 */
.ph-wall__tile img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* The proof row is gone; the wall carries the brand signal on its own. */

/* --- Foot: segments + stats ----------------------------------------------- */

.ph-hero__foot {
	position: relative;
	z-index: 2;
	margin-top: clamp(1.4rem, 3vw, 2.2rem);
}

/* --- Proof band ----------------------------------------------------------- */

/*
 * Dark, deliberately.
 *
 * The hero previously ended by fading out into white, which left the numbers —
 * the most substantiated thing on the page — sitting in the weakest position on
 * it. On the header and footer's own surface they close the section instead of
 * trailing off, and the page reads as bracketed rather than merely stopped.
 */
.ph-proof {
	position: relative;
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 1px;
	margin: 0;
	overflow: hidden;
	background: rgba(255, 255, 255, 0.08);
	border-radius: var(--r-lg);
	box-shadow: 0 24px 50px -30px rgba(11, 14, 28, 0.75);
}

/* One glow, matching the header's, so the band is not a flat slab. */
.ph-proof::before {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(70% 160% at 18% 0%, rgba(108, 134, 255, 0.35), transparent 60%),
		var(--pgpl-aurora, #0b0e1c);
	pointer-events: none;
}

.ph-proof > div {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column-reverse;
	gap: 0.3rem;
	padding: 1.25rem 1.2rem;
	background: transparent;
}

/* The 1px grid lines come from the gap; these give them something to sit on. */
.ph-proof > div + div {
	box-shadow: -1px 0 0 rgba(255, 255, 255, 0.08);
}

.ph-proof dt {
	color: rgba(226, 230, 255, 0.58);
	font-size: 0.73rem;
	font-weight: 600;
	letter-spacing: 0.07em;
	text-transform: uppercase;
}

.ph-proof dd {
	margin: 0;
	font-family: var(--ph-display);
	color: #fff;
	font-size: clamp(1.45rem, 2.6vw, 2rem);
	font-weight: 800;
	line-height: 1;
	letter-spacing: -0.025em;
	/* Columns of digits that do not jitter as the counts change. */
	font-variant-numeric: tabular-nums;
}

/*
 * Below this width there is no room for two columns. The wall goes rather than
 * shrinking: a 3D perspective grid squeezed into a phone is unreadable, and the
 * product grid further down shows the same artwork at a size that works.
 */
@media (max-width: 62rem) {
	.ph-hero__grid {
		grid-template-columns: minmax(0, 1fr);
		min-height: 0;
		text-align: center;
	}

	.ph-hero__lede { margin-inline: auto; }
	.ph-hero__promises { justify-content: center; }
	.ph-hero__cta,
	.ph-hero__proof { justify-content: center; }
	.ph-wall { display: none; }
	.ph-hero::before { mask-image: none; -webkit-mask-image: none; opacity: 0.5; }

	/*
	 * The price line is a flex row, so the centring above — which is text-align —
	 * passed straight over it and "from $3.49" stayed pinned to the left under a
	 * centred headline. Flex rows have to be told separately.
	 */
	.ph-hero__l3 { justify-content: center; }
}

@media (max-width: 48rem) {
	.ph-proof { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.ph-hero__cta .ph-btn { flex: 1 1 100%; }

	/*
	 * A second glow, low and right.
	 *
	 * One gradient pinned to 18% 0% lit the top-left corner and left everything
	 * below it flat — which on a single row is the whole band, but on two rows is
	 * only half of it, so the lower half read as a plain black rectangle with two
	 * figures loose in it. The pair is the same device the reviews band uses
	 * further down: ultra at the top, a trace of green at the bottom.
	 */
	.ph-proof::before {
		background:
			radial-gradient(85% 70% at 10% 0%, rgba(108, 134, 255, 0.34), transparent 62%),
			radial-gradient(75% 65% at 95% 100%, rgba(0, 182, 122, 0.15), transparent 60%),
			var(--pgpl-aurora, #0b0e1c);
	}

	/*
	 * Redrawn as a 2x2, not dropped.
	 *
	 * Losing the rules altogether left four figures floating in a large dark
	 * rectangle with nothing to say which belonged to which — a stat block only
	 * reads as a table of figures if it is ruled like one. A hairline down the
	 * middle and another between the rows costs nothing and restores it.
	 *
	 * Drawn as insets rather than left to the 1px grid gap: ::before paints the
	 * band's surface across the whole box, so the gap shows that gradient through
	 * rather than a light line.
	 */
	.ph-proof > div + div { box-shadow: none; }

	.ph-proof > div:nth-child(2n) {
		box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.08);
	}

	.ph-proof > div:nth-child(n + 3) {
		box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
	}

	.ph-proof > div:nth-child(2n):nth-child(n + 3) {
		box-shadow:
			inset 1px 0 0 rgba(255, 255, 255, 0.08),
			inset 0 1px 0 rgba(255, 255, 255, 0.08);
	}

	/*
	 * column-reverse puts the flex START at the bottom, so each cell packed its
	 * contents downward. On one row that is invisible; on two it is not — a label
	 * wrapping to a second line ("refreshed this month") pushed its own number up
	 * and left the number beside it sitting 19px lower. Packing to the top instead
	 * lands every figure on the same line whatever its label does.
	 */
	.ph-proof > div {
		justify-content: flex-end;
		gap: 0.4rem;
		padding: 1.15rem 1rem 1.25rem;
	}

	/*
	 * The figures carry this band, and at 23px against 105px-tall cells they were
	 * not carrying it — the block was mostly ground. Larger, and tracked in, so
	 * "16,718" and "Unlimited" both hold their cell without touching its rule.
	 */
	.ph-proof dd { font-size: clamp(1.45rem, 6.4vw, 2rem); }

	/*
	 * "Refreshed this month" cannot fit one line at this width without dropping
	 * the label below a legible size, so it is set to wrap well instead: balanced
	 * over two lines, with the tracking eased so the pair does not read as looser
	 * than the one-line labels beside it.
	 */
	.ph-proof dt {
		font-size: 0.71rem;
		letter-spacing: 0.055em;
		line-height: 1.32;
		text-wrap: balance;
	}
}

/* --- Reviews -------------------------------------------------------------- */

/*
 * Dark, and full-bleed.
 *
 * The page runs white from the hero to the footer, and white review cards on a
 * white ground had nothing to be seen against — the section read as more page
 * rather than as its own thing. Dropping it onto the same near-black surface as
 * the header, footer and proof band gives the page a rhythm, and it puts the
 * one green element on the page where green actually carries: the stars.
 */
.ph-reviews {
	position: relative;
	z-index: 1;
	margin-top: clamp(1.6rem, 4vw, 2.6rem);
	padding: clamp(1.5rem, 3vw, 2.2rem) 0;
	overflow: hidden;
	background: var(--pgpl-aurora, #0b0e1c);
}

/* One glow, matching the proof band above, so the surface is not a flat slab. */
.ph-reviews::before {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(60% 120% at 15% 0%, rgba(108, 134, 255, 0.28), transparent 62%),
		radial-gradient(50% 110% at 88% 100%, rgba(0, 182, 122, 0.14), transparent 62%);
	pointer-events: none;
}

/* Trustpilot's own green, which finally has a ground dark enough to sing on. */
.ph-stars {
	display: inline-flex;
	gap: 1px;
	color: #00d68f;
	line-height: 0;
}

.ph-rmarquee {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	/*
	 * The padding is load-bearing, not spacing.
	 *
	 * mask-image clips to this element's own box, so a card lifting 2px on hover
	 * moved outside it and had its top row of pixels masked away — the card
	 * appeared to be sliced off. This reserves room inside the mask for the
	 * lift; the negative margin cancels it so the section's rhythm is unchanged.
	 */
	padding: 6px 0;
	margin: -6px 0;
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.ph-rtrack {
	display: flex;
	gap: 0.6rem;
	width: max-content;
	/*
	 * flex-start, not stretch. Letting each card size to its own text keeps the
	 * row compact — with stretch, one four-line review sets the height of every
	 * card beside it.
	 */
	align-items: flex-start;
	will-change: transform;
}

/*
 * Opposite directions at unequal durations. Two rows moving the same way read
 * as one block sliding past; two moving against each other read as a field.
 */
.ph-rtrack--a { animation: ph-drift-r 78s linear infinite; }
.ph-rtrack--b { animation: ph-drift-l 92s linear infinite; }

/* Each row holds its cards twice, so 50% lands on an identical frame. */
@keyframes ph-drift-r {
	from { transform: translateX(-50%); }
	to   { transform: translateX(0); }
}

@keyframes ph-drift-l {
	from { transform: translateX(0); }
	to   { transform: translateX(-50%); }
}

/*
 * The rows do not pause on hover. focus-within is kept and is not the same
 * thing: a keyboard user has deliberately tabbed INTO a card, and letting it
 * slide away leaves the page focused on something they can no longer see.
 */
.ph-rmarquee:focus-within .ph-rtrack {
	animation-play-state: paused;
}

/*
 * ON PHONES THE MARQUEE IS A SWIPER, NOT AN ANIMATION.
 *
 * Each track is a ~4,000px composited layer drifting for 78–92s, and iOS
 * Safari rasterises the tiles of large moving layers LAZILY — on a phone the
 * first row rendered blank on load and the cards only appeared once WebKit
 * got around to painting that part of the layer. Desktop Chrome never shows
 * it, which is exactly why it shipped.
 *
 * So below 48rem the animation is off and each row is a native horizontal
 * scroller with snap points: no giant layer to rasterise (nothing to paint
 * late), and a phone user can actually hold and read a review instead of
 * chasing it — swiping is the better interaction at that size anyway.
 *
 * The aria-hidden cards are the marquee's seam copies. In a swiper they are
 * not decoration, they are the same six reviews twice — hidden.
 */
@media (max-width: 48rem) {
	.ph-rtrack--a,
	.ph-rtrack--b {
		animation: none;
	}

	/*
	 * No snap, and the seam copies STAY: the drift on phones is JavaScript
	 * walking scrollLeft (see main-page.js), because scroll content is
	 * painted eagerly where a transform layer is rasterised lazily. The
	 * duplicates are what let the walk wrap invisibly, exactly as they do
	 * for the desktop keyframes; snap would fight the sub-pixel steps.
	 */
	.ph-rtrack {
		width: auto;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		padding-inline: 0.9rem;
		will-change: auto;
	}

	.ph-rtrack::-webkit-scrollbar { display: none; }

	.ph-review {
		flex-basis: min(76vw, 300px);
	}

	/* Ease the fade so a snapped first card is not dimmed. */
	.ph-rmarquee {
		-webkit-mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
		mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
	}
}

/*
 * Glass, not a white slab. A solid card would punch a hole in the dark surface;
 * a translucent one lets the glow behind it through, so the row sits IN the
 * section rather than on top of it.
 */
.ph-review {
	position: relative;
	display: flex;
	flex: 0 0 clamp(214px, 19vw, 256px);
	flex-direction: column;
	gap: 0.45rem;
	margin: 0;
	padding: 0.8rem 0.9rem 0.75rem;
	background: rgba(255, 255, 255, 0.055);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: var(--r-md);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	transition: background-color 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
}

/*
 * The quotation mark, set large and faint. It is the oldest signal in print for
 * "these are someone else's words", and it does that job without spending a
 * single word of the card on saying so.
 */
.ph-review::before {
	content: "\201C";
	position: absolute;
	top: 0.2rem;
	right: 0.6rem;
	color: rgba(255, 255, 255, 0.12);
	font-size: 2.5rem;
	font-weight: 800;
	line-height: 1;
	pointer-events: none;
}

@media (hover: hover) and (pointer: fine) {
	.ph-review:hover {
		transform: translateY(-2px);
		background: rgba(255, 255, 255, 0.09);
		border-color: rgba(255, 255, 255, 0.2);
	}
}

/*
 * Explicitly reset, not inherited. GeneratePress styles <blockquote> with an
 * italic face and a left rule; that arrived here by accident and would have
 * changed silently on a theme update.
 */
.ph .ph-review__text {
	position: relative;
	margin: 0;
	padding: 0;
	color: rgba(255, 255, 255, 0.92);
	font-size: var(--t-xs);
	font-style: normal;
	line-height: 1.5;
	letter-spacing: -0.005em;
	border: 0;
	quotes: none;
}

.ph .ph-review__text::before,
.ph .ph-review__text::after { content: none; }

.ph-review__by {
	display: flex;
	gap: 0.45rem;
	align-items: center;
	margin-top: 0.1rem;
	padding-top: 0.5rem;
	border-top: 1px solid rgba(255, 255, 255, 0.1);
}

/*
 * A monogram, not a stock photo. These are real people who did not supply a
 * portrait, and inventing a face for a real reviewer is not a small liberty.
 *
 * The hue still comes from the name, but the lightness is inverted for the dark
 * ground — a pale disc that worked on white would be the brightest object in
 * the section here and would pull the eye off the words.
 */
.ph-review__avatar {
	display: inline-flex;
	flex: 0 0 24px;
	width: 24px;
	height: 24px;
	align-items: center;
	justify-content: center;
	color: hsl(var(--h, 230) 90% 84%);
	font-size: 0.68rem;
	font-weight: 800;
	background: hsl(var(--h, 230) 55% 24%);
	border-radius: 999px;
	box-shadow: inset 0 0 0 1px hsl(var(--h, 230) 70% 40%);
}

/* min-width:0 lets a long name ellipsis rather than widen the card. */
.ph-review__who { min-width: 0; }

.ph-review__name {
	font-family: var(--ph-display);
	display: block;
	color: #fff;
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: -0.01em;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

.ph-review__meta {
	display: block;
	color: rgba(226, 230, 255, 0.6);
	font-size: 0.67rem;
	font-weight: 500;
}

/* --- Sections ------------------------------------------------------------- */

/*
 * 7vw resolved to 88px top and bottom at desktop width, which on top of the
 * reviews section's own bottom padding left a 126px void above the products
 * heading. Sections need separating, not isolating.
 */
.ph-sec {
	padding: clamp(2rem, 4vw, 3rem) 0;
}

.ph-sec--tight { padding-top: 0; }

.ph-sec--alt {
	background: var(--ph-tint);
}

.ph-sec__head {
	display: flex;
	gap: 1.5rem;
	align-items: flex-end;
	justify-content: space-between;
	flex-wrap: wrap;
	margin-bottom: 2rem;
}

.ph-sec__head--center {
	justify-content: center;
	text-align: center;
}

.ph-eyebrow {
	display: block;
	color: var(--ph-mute-2);
	font-size: 0.7rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.ph-sec__title {
	font-family: var(--ph-display);
	margin: 0.5rem 0 0;
	color: var(--ph-ink);
	font-size: var(--t-2xl);
	font-weight: 800;
	line-height: 1.08;
	letter-spacing: -0.028em;
	text-wrap: balance;
}


/* --- Tabs ----------------------------------------------------------------- */

.ph-tabs {
	display: flex;
	gap: 0.4rem;
	flex-wrap: wrap;
	padding: 0.3rem;
	background: var(--ph-tint);
	border: 1px solid var(--ph-line);
	border-radius: 999px;
}

.ph-tab {
	padding: 0.5rem 1.05rem;
	color: var(--ph-mute);
	font-family: inherit;
	font-size: 0.85rem;
	font-weight: 600;
	background: none;
	border: 0;
	border-radius: 999px;
	cursor: pointer;
	transition: color 0.15s ease, background-color 0.15s ease;
}

.ph-tab.is-active {
	color: #fff;
	background: var(--ph-ink);
	box-shadow: 0 6px 16px -8px rgba(11, 14, 28, 0.55);
}

@media (hover: hover) and (pointer: fine) {
	.ph-tab:not(.is-active):hover { color: var(--ph-ink); background: #fff; }
}

/* --- Product grid --------------------------------------------------------- */

.ph-grid[hidden] { display: none; }

.ph-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 1.15rem;
}

.ph .ph-card {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	color: inherit;
	text-decoration: none;
	background: #fff;
	border-radius: var(--r-lg);
	box-shadow:
		0 0 0 1px rgba(11, 14, 28, 0.07),
		0 10px 24px -18px rgba(11, 14, 28, 0.45);
	transition: transform 0.2s ease, box-shadow 0.2s ease;
}

@media (hover: hover) and (pointer: fine) {
	.ph .ph-card:hover {
		transform: translateY(-4px);
		box-shadow:
			0 0 0 1px rgba(108, 134, 255, 0.4),
			0 26px 44px -24px rgba(11, 14, 28, 0.5);
	}
}

.ph-card__art {
	display: block;
	position: relative;
	aspect-ratio: 16 / 10;
	overflow: hidden;
	background: var(--ph-tint);
}

.ph-card__art img {
	position: relative;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.4s ease;
}

.ph .ph-card:hover .ph-card__art img { transform: scale(1.05); }

/*
 * Sits under the image; only ever seen when the image file is missing — the
 * library has records pointing at deleted files, and a broken <img> with an
 * empty alt renders as nothing at all.
 */
.ph-card__art::before {
	content: attr(data-letter);
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	color: rgba(11, 14, 28, 0.14);
	font-size: 3.2rem;
	font-weight: 800;
}

/*
 * The category, on the artwork.
 *
 * Beneath it, this was a grey line competing with the product name for the same
 * job and pushing the price further down. As a label on the image it costs the
 * body no height at all.
 */
.ph-card__cat {
	position: absolute;
	top: 0.65rem;
	left: 0.65rem;
	max-width: 60%;
	padding: 0.24rem 0.6rem;
	color: var(--ph-ink);
	font-size: 0.64rem;
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	background: rgba(255, 255, 255, 0.92);
	border-radius: 999px;
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

/*
 * The price as a tag on the artwork, matching the hero's.
 *
 * Beneath the title it was a line of text under a rule, competing with the
 * product name for the same moment. Up here it is the first thing read after
 * the picture — which on a store whose whole argument is $3.49 is where it
 * belongs — and it repeats the hero's device, so the page has one idea about
 * how a price looks rather than two.
 */
.ph-card__price {
	font-family: var(--ph-display);
	position: absolute;
	right: 0.65rem;
	bottom: 0.65rem;
	padding: 0.22rem 0.6rem;
	color: #fff;
	font-size: var(--t-md);
	font-weight: 800;
	letter-spacing: -0.01em;
	font-variant-numeric: tabular-nums;
	background: linear-gradient(135deg, var(--pgpl-ultra), #5b32e8);
	border-radius: 0.35rem;
	box-shadow: 0 8px 18px -8px rgba(60, 80, 255, 0.85);
	/* The same 1.5deg tilt as the hero tag, so they read as the same object. */
	transform: rotate(-1.5deg);
}

.ph-card__body {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	gap: 0.85rem;
	padding: 0.9rem 0.9rem 0.9rem;
}

.ph-card__name {
	font-family: var(--ph-display);
	display: -webkit-box;
	overflow: hidden;
	color: var(--ph-ink);
	font-size: var(--t-md);
	font-weight: 700;
	line-height: 1.35;
	letter-spacing: -0.01em;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
}

/*
 * A real button, full width, pinned to the bottom.
 *
 * margin-top:auto keeps every button on the same line across a row whatever the
 * title height — which is what the old rule-and-price row was doing, without
 * the empty gap it left when a title ran to one line.
 */
.ph-card__btn {
	display: flex;
	gap: 0.4rem;
	align-items: center;
	justify-content: center;
	margin-top: auto;
	padding: 0.6rem 0.9rem;
	color: var(--ph-ink);
	font-size: var(--t-xs);
	font-weight: 700;
	background: var(--ph-tint);
	border-radius: var(--r-sm);
	transition: color 0.18s ease, background-color 0.18s ease;
}

.ph-card__btn svg { transition: transform 0.18s ease; }

/*
 * Driven by hovering the CARD, not the button. The whole card is the link, so
 * lighting up only when the pointer crosses the button would suggest the rest
 * of it is not clickable.
 */
@media (hover: hover) and (pointer: fine) {
	.ph .ph-card:hover .ph-card__btn {
		color: #fff;
		background: var(--pgpl-ultra);
	}

	.ph .ph-card:hover .ph-card__btn svg { transform: translateX(3px); }
}

/* --- The "browse all" tile ------------------------------------------------ */

/*
 * The eighth cell of the grid, not a pill underneath it.
 *
 * A lone ghost button below the products was the weakest position on the page
 * for the one link that moves someone into the catalogue: after eight cards the
 * eye has already left. As a cell it completes the row, and it can carry the
 * shelf count — which is the argument for clicking, and a button reading
 * "Browse all Premium Plugins" has no room to make it.
 */
.ph .ph-more {
	display: flex;
	flex-direction: column;
	justify-content: center;
	position: relative;
	overflow: hidden;
	padding: 1.4rem 1.3rem;
	color: #fff;
	text-decoration: none;
	background: linear-gradient(150deg, var(--pgpl-ultra), #4a1fd0 65%, #2a0f8a);
	border-radius: var(--r-lg);
	/* Contains the mosaic's blend, or it would composite against the page. */
	isolation: isolate;
	box-shadow: 0 18px 36px -22px rgba(60, 80, 255, 0.9);
	transition: transform 0.2s ease, box-shadow 0.2s ease;
}

/*
 * The mosaic: nine real products from the shelf this links to.
 *
 * The tile asserted "152 more" over a flat gradient. A wall of the actual
 * products makes the same claim visually — and because it is drawn from the
 * shelf itself, it cannot advertise something that is not there.
 */
.ph-more__mosaic {
	position: absolute;
	inset: 0;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	grid-auto-rows: 1fr;
	gap: 2px;
	/* Slightly oversized and offset, so no tile reads as a neat framed edge. */
	transform: scale(1.12) rotate(-3deg);
	/*
	 * Explicit stacking. ::before is generated as the FIRST child, so without
	 * this the mosaic — a real element, later in the DOM — paints on top of the
	 * scrim and the type sits directly on the artwork.
	 */
	z-index: 0;
	/*
	 * Duotone, not a curtain.
	 *
	 * Covering the mosaic with a 94% wash made the type legible and the pictures
	 * pointless — the tile was a flat gradient again, only slower to render.
	 * Blending on luminosity keeps every shape and edge of the artwork while
	 * forcing it into the tile's own blue, so the products stay clearly visible
	 * AND white text still holds over them.
	 */
	mix-blend-mode: luminosity;
	opacity: 0.6;
	filter: contrast(1.12) brightness(1.08);
	pointer-events: none;
}

.ph-more__mosaic img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/*
 * A scrim over the TEXT ONLY.
 *
 * Weighted to the left where the number, label and button sit, and gone by 60%
 * so the right of the tile shows the mosaic at full strength. The previous
 * version covered the whole tile evenly, which is exactly why nothing behind it
 * could be made out.
 */
.ph .ph-more--art::before {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(100deg, rgba(28, 16, 160, 0.82) 6%, rgba(34, 19, 172, 0.46) 40%, transparent 60%);
	z-index: 1;
	pointer-events: none;
}

/* Without artwork the tile keeps its own bloom rather than rendering flat. */
.ph .ph-more:not(.ph-more--art)::before {
	content: "";
	position: absolute;
	top: -30%;
	right: -20%;
	width: 70%;
	height: 90%;
	background: radial-gradient(circle, rgba(255, 255, 255, 0.22), transparent 70%);
	pointer-events: none;
}

@media (hover: hover) and (pointer: fine) {
	.ph .ph-more:hover {
		transform: translateY(-4px);
		box-shadow: 0 30px 48px -22px rgba(60, 80, 255, 0.95);
	}
}

.ph-more__n {
	font-family: var(--ph-display);
	position: relative;
	z-index: 2;
	color: #fff;
	font-size: clamp(2rem, 3.4vw, 2.7rem);
	font-weight: 800;
	line-height: 1;
	letter-spacing: -0.035em;
	font-variant-numeric: tabular-nums;
	text-shadow: 0 2px 14px rgba(12, 6, 60, 0.55);
}

.ph-more__label {
	position: relative;
	z-index: 2;
	margin-top: 0.2rem;
	color: rgba(255, 255, 255, 0.9);
	font-size: var(--t-sm);
	font-weight: 600;
	line-height: 1.3;
	text-shadow: 0 1px 10px rgba(12, 6, 60, 0.5);
}

.ph-more__go {
	display: inline-flex;
	gap: 0.35rem;
	align-items: center;
	position: relative;
	z-index: 2;
	margin-top: 1rem;
	padding: 0.45rem 0.9rem;
	color: var(--pgpl-ultra);
	font-size: var(--t-xs);
	font-weight: 800;
	background: #fff;
	border-radius: 999px;
	align-self: flex-start;
	transition: transform 0.18s ease;
}

.ph .ph-more:hover .ph-more__go { transform: translateX(3px); }

/* --- Section lede --------------------------------------------------------- */

.ph-sec__lede {
	max-width: 56ch;
	margin: 0.9rem auto 0;
	color: var(--ph-mute);
}

/* --- How it works: three mocked moments ----------------------------------- */

/*
 * Each step shows its moment rather than describing it.
 *
 * A numbered rail with a paragraph underneath was still three blocks of prose,
 * and two of the three were re-stating what the pricing section and the FAQ
 * already cover. Drawing the actual moment gives the section information the
 * rest of the page does not have — and it is the only place the product is
 * shown in use.
 *
 * Every mock is HTML and CSS: no screenshots to go stale, nothing extra to
 * download, and they restyle with the rest of the page.
 */
.ph-flow {
	/*
	 * Shared by the frames, the badges and the rail that threads them, so the
	 * three cannot drift apart — the rail's position is derived from the frame
	 * height rather than guessed alongside it.
	 */
	--flow-mock-h: 132px;
	--flow-mock-mb: 1.1rem;
	--flow-n: 30px;

	position: relative;
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 1.15rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * The rail.
 *
 * Three steps drawn as three columns are three separate things, and the numbers
 * were doing all the work of saying otherwise — 1, 2 and 3 floating with nothing
 * between them. A line through the badge centres makes the section a route
 * rather than a set, which is the whole claim the heading makes.
 *
 * It can sit at one fixed height because every badge lands at the same height:
 * the frames above them share one. Each badge then punches the line with a ring
 * in the band's own colour, so the rail reads as passing behind the stations.
 *
 * Faded at both ends rather than stopped at the outer badges — those centres sit
 * a sixth of the row in from each edge and would have to be recomputed for every
 * column count the grid takes.
 */
.ph-flow::before {
	content: "";
	position: absolute;
	top: calc(var(--flow-mock-h) + var(--flow-mock-mb) + (var(--flow-n) / 2));
	left: 0;
	right: 0;
	height: 1px;
	/* top is the badge centre, so the 1px band is pulled back onto it. */
	transform: translateY(-0.5px);
	background: linear-gradient(90deg, transparent, var(--ph-line) 14%, var(--ph-line) 86%, transparent);
	pointer-events: none;
}

/*
 * No card. Each step already contains a framed mock, so wrapping that in a
 * white box was a frame inside a frame — and it made this section look exactly
 * like the pricing table, which shared the same tinted band.
 */
.ph-flow__step {
	position: relative;
	padding: 0;
}

/* --- The mock frame --- */

.ph-flow__mock {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 0.4rem;
	height: var(--flow-mock-h);
	margin-bottom: var(--flow-mock-mb);
	padding: 0.8rem;
	overflow: hidden;
	/*
	 * A trace of a gradient rather than flat #fff. These are meant to read as
	 * screens, and on a tinted band three flat white rectangles read as three
	 * holes cut in it.
	 */
	background: linear-gradient(180deg, #ffffff, #fbfbff);
	border-radius: var(--r-md);
	box-shadow:
		0 0 0 1px rgba(11, 14, 28, 0.06),
		0 10px 22px -18px rgba(11, 14, 28, 0.4);
	transition: transform 0.2s ease, box-shadow 0.2s ease;
}

/*
 * Driven by the STEP, not the frame. The prose under each mock belongs to it,
 * and lighting up only when the pointer happens to cross the picture would
 * suggest the two are separate things.
 */
@media (hover: hover) and (pointer: fine) {
	.ph-flow__step:hover .ph-flow__mock {
		transform: translateY(-3px);
		box-shadow:
			0 0 0 1px rgba(108, 134, 255, 0.35),
			0 22px 36px -24px rgba(11, 14, 28, 0.5);
	}
}

.ph-flow__n {
	position: relative;
	z-index: 1;
	/*
	 * flex, not inline-flex. As an inline box the badge sat on a text baseline
	 * and the strut above it pushed it 1.5px below where the rail's arithmetic
	 * says it is — which on a 1px line is the difference between threaded and
	 * nearly threaded. Block-level, its top is exactly the frame plus its margin.
	 */
	display: flex;
	width: var(--flow-n);
	height: var(--flow-n);
	align-items: center;
	justify-content: center;
	margin-bottom: 0.6rem;
	color: #fff;
	font-size: 0.82rem;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	background: var(--pgpl-ultra);
	border-radius: 999px;
	/*
	 * Three shadows doing three jobs: the first is the band's own colour and is
	 * what cuts the rail cleanly either side of the badge; the second is the
	 * accent at low alpha, so the badge has a halo instead of sitting on the line
	 * like a bead; the third grounds it against the band.
	 */
	box-shadow:
		0 0 0 4px var(--ph-tint),
		0 0 0 5px rgba(108, 134, 255, 0.26),
		0 6px 14px -6px rgba(60, 80, 255, 0.65);
}

.ph-flow__title {
	font-family: var(--ph-display);
	margin: 0 0 0.3rem;
	color: var(--ph-ink);
	font-size: var(--t-lg);
	font-weight: 700;
	letter-spacing: -0.01em;
}

.ph-flow__body {
	margin: 0;
	color: var(--ph-mute);
	font-size: var(--t-md);
	line-height: 1.5;
}

/* --- 1. Choosing a plan --- */

.ph-mockplan {
	display: flex;
	gap: 0.5rem;
	align-items: center;
	padding: 0.42rem 0.6rem;
	background: var(--ph-tint);
	border-radius: var(--r-sm);
	box-shadow: inset 0 0 0 1px rgba(11, 14, 28, 0.07);
}

.ph-mockplan span {
	flex: 0 0 12px;
	width: 12px;
	height: 12px;
	border-radius: 999px;
	box-shadow: inset 0 0 0 1.5px rgba(11, 14, 28, 0.2);
}

.ph-mockplan b {
	flex: 1 1 auto;
	color: var(--ph-ink);
	font-size: 0.72rem;
	font-weight: 700;
}

.ph-mockplan i {
	color: var(--ph-mute-2);
	font-size: 0.72rem;
	font-style: normal;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

/* The chosen one. A ring plus a filled dot, so it reads as a radio, not a hover. */
.ph-mockplan.is-on {
	box-shadow: inset 0 0 0 1.5px var(--pgpl-ultra);
}

.ph-mockplan.is-on span {
	background: var(--pgpl-ultra);
	box-shadow: inset 0 0 0 2.5px #fff, 0 0 0 1.5px var(--pgpl-ultra);
}

.ph-mockplan.is-on i { color: var(--pgpl-ultra); }

/* --- 2. Searching --- */

.ph-mocksearch {
	display: flex;
	gap: 0.4rem;
	align-items: center;
	padding: 0.45rem 0.6rem;
	color: var(--ph-mute-2);
	font-size: 0.74rem;
	background: var(--ph-tint);
	border-radius: 999px;
	box-shadow: inset 0 0 0 1.5px rgba(108, 134, 255, 0.45);
}

.ph-mocksearch span { color: var(--ph-ink); font-weight: 600; }

.ph-mockrow {
	display: flex;
	gap: 0.45rem;
	align-items: center;
	padding: 0.35rem 0.45rem;
	background: var(--ph-tint);
	border-radius: var(--r-sm);
	box-shadow: inset 0 0 0 1px rgba(11, 14, 28, 0.06);
}

/* The second result is half-faded, so the list reads as continuing. */
.ph-mockrow--fade { opacity: 0.45; }

.ph-mockrow__art {
	flex: 0 0 26px;
	height: 20px;
	background: linear-gradient(135deg, #c9d2ff, #a9baff);
	border-radius: var(--r-sm);
}

.ph-mockrow__lines { flex: 1 1 auto; display: flex; flex-direction: column; gap: 3px; }

.ph-mockrow__lines i {
	display: block;
	height: 4px;
	background: rgba(11, 14, 28, 0.14);
	border-radius: 999px;
}

.ph-mockrow__lines i:first-child { width: 78%; }
.ph-mockrow__lines i:last-child  { width: 44%; }

.ph-mockrow__price {
	color: var(--ph-ink);
	font-size: 0.68rem;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
}

/* --- 3. Installing --- */

.ph-mockzip {
	display: flex;
	gap: 0.5rem;
	align-items: center;
	padding: 0.5rem 0.6rem;
	color: var(--pgpl-ultra);
	background: var(--ph-tint);
	border-radius: var(--r-sm);
	box-shadow: inset 0 0 0 1px rgba(11, 14, 28, 0.07);
}

.ph-mockzip b {
	color: var(--ph-ink);
	font-size: 0.72rem;
	font-weight: 700;
}

.ph-mockbar {
	display: block;
	height: 6px;
	overflow: hidden;
	background: rgba(11, 14, 28, 0.08);
	border-radius: 999px;
}

.ph-mockbar i {
	display: block;
	width: 100%;
	height: 100%;
	background: linear-gradient(90deg, var(--pgpl-ultra), #7b83ff);
	border-radius: 999px;
}

.ph-mockdone {
	display: inline-flex;
	gap: 0.3rem;
	align-items: center;
	align-self: flex-start;
	padding: 0.28rem 0.6rem;
	color: #15803d;
	font-size: 0.7rem;
	font-weight: 700;
	background: #dcfce7;
	border-radius: 999px;
}

/* --- Pricing -------------------------------------------------------------- */

/*
 * What every plan shares, said once.
 *
 * "All 16,718 products" and "Instant auto-updates" appeared in all four cards,
 * so three quarters of every feature list was identical and the eye had to work
 * to find what actually differed. Lifting the common ground out is why this
 * reads as considered rather than generated.
 */
.ph-common {
	display: flex;
	gap: 0.75rem 1.4rem;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	margin-bottom: 1.8rem;
	padding: 0.85rem 1.4rem;
	background: var(--ph-tint);
	border-radius: var(--r-full);
	box-shadow: inset 0 0 0 1px rgba(11, 14, 28, 0.06);
}

.ph-common__label {
	color: var(--ph-mute-2);
	font-size: var(--t-xs);
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.ph-common ul {
	display: flex;
	gap: 0.4rem 1.3rem;
	flex-wrap: wrap;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ph-common li {
	display: flex;
	gap: 0.35rem;
	align-items: center;
	color: var(--ph-ink);
	font-size: var(--t-sm);
	font-weight: 600;
}

.ph-common svg { color: #16a34a; flex: 0 0 auto; }

/* --- The cards ------------------------------------------------------------ */

.ph-plans {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 1rem;
	/* Room for the flag and for the recommended card's negative margin. */
	padding: 1.4rem 0.2rem 0.6rem;
	align-items: stretch;
	/*
	 * NOT align-items:start. Cards must stretch to a common height, otherwise
	 * margin-top:auto pins each button to its own card's bottom and the four
	 * CTAs land on four different lines.
	 */
}

.ph-plan {
	display: flex;
	flex-direction: column;
	position: relative;
	padding: 1.5rem 1.4rem;
	background: #fff;
	border-radius: var(--r-lg);
	/* Firmer edge: these now sit on white rather than on the tinted band. */
	box-shadow:
		0 0 0 1px rgba(11, 14, 28, 0.1),
		0 14px 30px -22px rgba(11, 14, 28, 0.45);
	transition: box-shadow 0.2s ease, transform 0.2s ease;
}

@media (hover: hover) and (pointer: fine) {
	.ph-plan:not(.is-best):hover {
		transform: translateY(-3px);
		box-shadow:
			0 0 0 1px rgba(11, 14, 28, 0.14),
			0 22px 38px -22px rgba(11, 14, 28, 0.45);
	}
}

/*
 * The recommended plan is a different object, not the same card with a ring.
 *
 * An outline said "this one" quietly enough that the eye still had to compare
 * four equal things. On the page's own near-black — the surface the header,
 * reviews and proof band already use — it stops being one of four and becomes
 * the answer, with the others as alternatives to it. That is the whole job of a
 * recommended plan.
 */
.ph-plan.is-best {
	position: relative;
	z-index: 1;
	margin: -0.6rem -0.2rem;
	padding: 2.1rem 1.6rem;
	background:
		radial-gradient(80% 120% at 20% 0%, rgba(108, 134, 255, 0.35), transparent 60%),
		var(--pgpl-aurora, #0b0e1c);
	box-shadow: 0 34px 60px -30px rgba(30, 20, 140, 0.85);
}

.ph-plan.is-best .ph-plan__name,
.ph-plan.is-best .ph-plan__price { color: #fff; }

.ph-plan.is-best .ph-plan__note,
.ph-plan.is-best .ph-plan__price small,
.ph-plan.is-best .ph-plan__each { color: rgba(226, 230, 255, 0.6); }

.ph-plan.is-best .ph-plan__sub { color: #6ee7a8; }

.ph-plan.is-best .ph-plan__rate { border-top-color: rgba(255, 255, 255, 0.14); }
.ph-plan.is-best .ph-plan__rate-n { color: rgba(226, 230, 255, 0.7); }
.ph-plan.is-best .ph-plan__rate-n b { color: #fff; }
.ph-plan.is-best .ph-plan__bar { background: rgba(255, 255, 255, 0.14); }
.ph-plan.is-best .ph-plan__bar i { background: linear-gradient(90deg, #7b83ff, #a9baff); }

.ph-plan.is-best .ph-plan__feats li { color: rgba(226, 230, 255, 0.82); }
.ph-plan.is-best .ph-plan__feats li::before { border-color: #6ee7a8; }

/* White button on dark, so it is the brightest thing in the section. */
.ph .ph-plan.is-best .ph-plan__cta,
.ph .ph-plan.is-best .ph-plan__cta:hover {
	color: var(--pgpl-aurora, #0b0e1c);
	background: #fff;
	border-color: transparent;
}

.ph-plan__flag {
	position: absolute;
	top: -0.72rem;
	left: 1.4rem;
	padding: 0.24rem 0.7rem;
	color: #fff;
	font-size: var(--t-xs);
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	background: var(--pgpl-ultra);
	border-radius: var(--r-full);
	box-shadow: 0 6px 16px -6px rgba(60, 80, 255, 0.9);
}

.ph-plan__name {
	margin: 0;
	color: var(--ph-ink);
	font-size: var(--t-lg);
	font-weight: 700;
	letter-spacing: -0.01em;
}

.ph-plan__note {
	margin: 0.1rem 0 1rem;
	color: var(--ph-mute-2);
	font-size: var(--t-sm);
}

/*
 * The period sits BELOW the amount, not beside it.
 *
 * Inline on a baseline, "₹11,346.98 one time" wrapped the label onto a second
 * line and knocked that card's rows out of step with the other three. Stacking
 * it means the layout holds for any currency and any length — which a row of
 * four cards has to, since one long price breaks all of them.
 */
.ph-plan__price {
	display: flex;
	flex-direction: column;
	margin: 0;
	color: var(--ph-ink);
}

.ph-plan__price span {
	font-family: var(--ph-display);
	/* Shrinks as the string lengthens, so ₹11,347 still fits one line. */
	font-size: clamp(1.9rem, 2.6vw, 2.6rem);
	white-space: nowrap;
	font-weight: 800;
	line-height: 1;
	letter-spacing: -0.04em;
	font-variant-numeric: tabular-nums;
}

.ph-plan__price small {
	margin-top: 0.15rem;
	color: var(--ph-mute-2);
	font-size: var(--t-sm);
	font-weight: 600;
}

/*
 * Always present, even when empty. Only two of the four plans have a savings
 * line, and without a reserved slot the rows below sat at two different heights
 * across the grid — which reads as a broken table.
 */
.ph-plan__sub {
	min-height: 1.3rem;
	margin: 0.5rem 0 0;
	/*
	 * Darker than the green used elsewhere, because this one sits on white.
	 * #16a34a measures 3.29:1 there — fine as a border or an icon, under the
	 * 4.5 WCAG asks of body text. The variant on the highlighted card keeps its
	 * lighter green, which is already 12:1 on that dark surface.
	 */
	color: #14763a;
	font-size: var(--t-sm);
	font-weight: 600;
}

/*
 * What it works out at per product.
 *
 * The number this store owns and had never stated: $99 across 16,718 products
 * is six tenths of a penny each. Computed from the live catalogue count, so it
 * cannot drift, and phrased as "under a cent" below one cent because "$0.01"
 * there would be a rounding lie.
 */
.ph-plan__each {
	margin: 0.35rem 0 0;
	color: var(--ph-mute-2);
	font-size: var(--t-xs);
	font-weight: 600;
	letter-spacing: 0.01em;
}

/* --- The download rate, drawn to scale ------------------------------------ */

/*
 * The one real difference between these plans.
 *
 * As four identical grey pills reading "30 / 35 / 100 downloads a day", a
 * threefold difference looked like a rounding error. A bar shows the ratio at a
 * glance, which is the actual decision being made here.
 */
.ph-plan__rate {
	margin: 1.2rem 0 0;
	padding-top: 1.1rem;
	border-top: 1px solid var(--ph-line-2);
}

.ph-plan__rate-n {
	display: block;
	margin-bottom: 0.5rem;
	color: var(--ph-mute);
	font-size: var(--t-sm);
	font-weight: 600;
}

.ph-plan__rate-n b {
	font-family: var(--ph-display);
	color: var(--ph-ink);
	font-size: 1.35rem;
	font-weight: 800;
	letter-spacing: -0.02em;
	font-variant-numeric: tabular-nums;
}

.ph-plan__bar {
	display: block;
	height: 6px;
	overflow: hidden;
	background: rgba(11, 14, 28, 0.07);
	border-radius: var(--r-full);
}

.ph-plan__bar i {
	display: block;
	height: 100%;
	background: linear-gradient(90deg, #a9baff, var(--pgpl-ultra));
	border-radius: var(--r-full);
}

.ph-plan.is-best .ph-plan__bar i {
	background: linear-gradient(90deg, var(--pgpl-ultra), #5b32e8);
}

/* --- What differs --------------------------------------------------------- */

.ph-plan__feats {
	margin: 1.1rem 0 1.4rem;
	padding: 0;
	list-style: none;
}

.ph-plan__feats li {
	position: relative;
	margin-bottom: 0.5rem;
	padding-left: 1.4rem;
	color: var(--ph-mute);
	font-size: var(--t-sm);
	line-height: 1.45;
}

/* A drawn tick, so the list needs no icon font and no extra markup. */
.ph-plan__feats li::before {
	content: "";
	position: absolute;
	top: 0.36rem;
	left: 0.15rem;
	width: 0.4rem;
	height: 0.7rem;
	border: solid #16a34a;
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

/* margin-top:auto keeps every button on one line whatever the list length. */
.ph .ph-plan__cta {
	margin-top: auto;
	width: 100%;
	padding: 0.75rem 1rem;
	font-size: var(--t-md);
}

/* --- Reassurance ---------------------------------------------------------- */

.ph-plans__foot {
	display: flex;
	gap: 0.45rem;
	align-items: center;
	justify-content: center;
	margin: 1.6rem 0 0;
	color: var(--ph-mute-2);
	font-size: var(--t-sm);
	font-weight: 600;
}

.ph-plans__foot svg { color: #16a34a; flex: 0 0 auto; }

/* --- FAQ ------------------------------------------------------------------ */

/*
 * Two columns, because a single centred one wasted the page.
 *
 * Six short rows stacked in a 900px column left most of the width empty and
 * gave the section no shape at all. The heading beside the questions uses the
 * measure, and the aside carries what a FAQ should always end with: a way to
 * ask the thing it did not answer.
 */
.ph-faq-grid {
	display: grid;
	grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.4fr);
	gap: clamp(2rem, 5vw, 4.5rem);
	align-items: start;
}

.ph-faq-aside {
	position: sticky;
	top: 6rem;
}

.ph-faq-aside .ph-sec__title { margin: 0.5rem 0 0; }

.ph-faq-aside__body {
	max-width: 34ch;
	margin: 1rem 0 1.4rem;
	color: var(--ph-mute);
	font-size: var(--t-md);
}

.ph .ph-faq-aside__link {
	display: inline-flex;
	gap: 0.4rem;
	align-items: center;
	padding: 0.6rem 1.1rem;
	color: var(--ph-ink);
	font-size: var(--t-sm);
	font-weight: 700;
	text-decoration: none;
	background: #fff;
	border-radius: var(--r-full);
	box-shadow: 0 0 0 1px rgba(11, 14, 28, 0.1);
	transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.ph-faq-aside__link svg { transition: transform 0.15s ease; }

@media (hover: hover) and (pointer: fine) {
	.ph .ph-faq-aside__link:hover {
		transform: translateY(-1px);
		box-shadow:
			0 0 0 1px rgba(108, 134, 255, 0.45),
			0 12px 22px -12px rgba(11, 14, 28, 0.45);
	}

	.ph .ph-faq-aside__link:hover svg { transform: translateX(3px); }
}

.ph-faq {
	border-top: 1px solid var(--ph-line);
}

.ph-faq__item {
	border-bottom: 1px solid var(--ph-line);
}

.ph-faq__q {
	display: flex;
	gap: 1rem;
	align-items: center;
	justify-content: space-between;
	padding: 1.15rem 0.25rem;
	color: var(--ph-ink);
	font-size: var(--t-lg);
	font-weight: 700;
	letter-spacing: -0.01em;
	cursor: pointer;
	list-style: none;
	transition: color 0.15s ease;
}

.ph-faq__q::-webkit-details-marker { display: none; }

@media (hover: hover) and (pointer: fine) {
	.ph-faq__q:hover { color: var(--pgpl-ultra); }
}

.ph-faq__sign {
	display: inline-flex;
	flex: 0 0 32px;
	width: 32px;
	height: 32px;
	align-items: center;
	justify-content: center;
	color: var(--ph-mute);
	background: #fff;
	border-radius: var(--r-full);
	box-shadow: inset 0 0 0 1px var(--ph-line);
	transition: color 0.18s ease, background-color 0.18s ease;
}

/* The plus loses its vertical stroke and becomes a minus. */
.ph-faq__bar { transition: opacity 0.18s ease, transform 0.18s ease; }

.ph-faq__item[open] .ph-faq__bar {
	opacity: 0;
	transform: rotate(90deg);
	transform-origin: center;
}

.ph-faq__item[open] .ph-faq__sign {
	color: #fff;
	background: var(--pgpl-ultra);
	box-shadow: none;
}

.ph-faq__a {
	padding: 0 3rem 1.4rem 0.25rem;
}

.ph-faq__a p {
	margin: 0;
	color: var(--ph-mute);
	font-size: var(--t-md);
	line-height: 1.65;
}

/* --- Reviews from the blog ------------------------------------------------ */

.ph-journal__all {
	display: inline-flex;
	gap: 0.4rem;
	align-items: center;
	color: var(--ph-ink);
	font-size: var(--t-sm);
	font-weight: 700;
	text-decoration: none;
}

.ph-journal__all svg { transition: transform 0.15s ease; }
.ph .ph-journal__all:hover svg { transform: translateX(3px); }

.ph-journal__grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 1.15rem;
}

/*
 * No card.
 *
 * The white box with a border and a shadow is what made these read as a
 * template — every blog ships that card. Letting the artwork and type sit
 * directly on the page is how an editorial site does it, and it moves the
 * attention onto the screenshot rather than the container around it.
 */
/*
 * A review card, not a blog card.
 *
 * The old version showed a thumbnail and a headline — the same object every
 * blog ships. These posts are reviews OF something, and the site's own
 * generator already records what: item type and item name. Leading with the
 * product is what turns a blog roll into a review index, and it is information
 * no amount of card styling could have added.
 */
.ph .ph-post {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	color: inherit;
	text-decoration: none;
	background: #fff;
	border-radius: var(--r-lg);
	box-shadow:
		0 0 0 1px rgba(11, 14, 28, 0.08),
		0 12px 28px -20px rgba(11, 14, 28, 0.45);
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

@media (hover: hover) and (pointer: fine) {
	.ph .ph-post:hover {
		transform: translateY(-5px);
		box-shadow:
			0 0 0 1px rgba(108, 134, 255, 0.45),
			0 30px 50px -26px rgba(11, 14, 28, 0.5);
	}
}

/*
 * Shorter than before. These are vendor marketing banners, busy and loud — the
 * less of each one on screen, the less four of them fight each other. The card
 * now earns its space with what it says, not with how much picture it shows.
 */
.ph-post__art {
	display: block;
	position: relative;
	aspect-ratio: 2 / 1;
	overflow: hidden;
	background: var(--ph-tint);
}

.ph-post__art img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

.ph .ph-post:hover .ph-post__art img { transform: scale(1.05); }

/* What was reviewed — Theme, Plugin — read straight from the post. */
.ph-post__kind {
	position: absolute;
	top: 0.6rem;
	left: 0.6rem;
	padding: 0.2rem 0.6rem;
	color: #fff;
	font-size: var(--t-xs);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	background: rgba(11, 14, 28, 0.72);
	border-radius: var(--r-full);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
}

.ph-post__body {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	gap: 0.35rem;
	padding: 1rem 1.1rem 0.95rem;
}

/*
 * The product name, in the accent and above the headline.
 *
 * Someone scanning for "is Foxiz any good" is looking for the product, not the
 * article title — so the product is what they should hit first.
 */
.ph-post__item {
	color: var(--pgpl-ultra);
	font-size: var(--t-xs);
	font-weight: 800;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

.ph-post__title {
	display: -webkit-box;
	overflow: hidden;
	color: var(--ph-ink);
	font-family: var(--ph-display);
	font-size: var(--t-md);
	font-weight: 700;
	line-height: 1.26;
	letter-spacing: -0.02em;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	transition: color 0.2s ease;
}

@media (hover: hover) and (pointer: fine) {
	.ph .ph-post:hover .ph-post__title { color: var(--pgpl-ultra); }
}

/* The store's own meta description: a written summary, not a truncated intro. */
.ph-post__desc {
	display: -webkit-box;
	overflow: hidden;
	color: var(--ph-mute);
	font-size: var(--t-sm);
	line-height: 1.55;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
}

/*
 * margin-top:auto pins this row to the bottom whatever the title height, so the
 * dates line up across the row.
 */
.ph-post__foot {
	display: flex;
	gap: 0.45rem;
	align-items: center;
	margin-top: auto;
	padding-top: 0.85rem;
	color: var(--ph-mute-2);
	font-size: var(--t-xs);
	font-weight: 600;
	border-top: 1px solid var(--ph-line-2);
}

/* A dot rather than a "·", which sits on the baseline and reads as a typo. */
.ph-post__dot {
	width: 3px;
	height: 3px;
	background: currentColor;
	border-radius: 50%;
	opacity: 0.6;
}

.ph-post__go {
	display: inline-flex;
	width: 26px;
	height: 26px;
	align-items: center;
	justify-content: center;
	margin-left: auto;
	color: var(--ph-mute);
	background: var(--ph-tint);
	border-radius: var(--r-full);
	transition: color 0.2s ease, background-color 0.2s ease, transform 0.2s ease;
}

.ph .ph-post:hover .ph-post__go {
	color: #fff;
	background: var(--pgpl-ultra);
	transform: translateX(2px);
}

/* --- Responsive ----------------------------------------------------------- */

@media (max-width: 68rem) {
	.ph-grid,
	.ph-plans,
	.ph-journal__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

	/*
	 * One column turns the sequence on its side.
	 *
	 * Stacked, each step arrived as picture, then number, then prose — the mock
	 * landed before the reader knew which step they were looking at — and the
	 * horizontal rail had nothing left to thread. Re-ordered into a timeline: the
	 * number and its title on one line, the claim under it, the mock beneath as
	 * the evidence, with the rail running down the gutter the badges already sit
	 * in and carrying the eye from one step to the next.
	 *
	 * Grid placement only. The markup order is untouched, so the order a screen
	 * reader announces is the order it always had.
	 */
	.ph-flow {
		grid-template-columns: minmax(0, 1fr);
		gap: 1.6rem;
	}

	.ph-flow::before { display: none; }

	.ph-flow__step {
		display: grid;
		grid-template-columns: var(--flow-n) minmax(0, 1fr);
		column-gap: 0.85rem;
		align-items: start;
	}

	.ph-flow__n {
		grid-area: 1 / 1;
		align-self: center;
		margin-bottom: 0;
	}

	.ph-flow__title {
		grid-area: 1 / 2;
		align-self: center;
		margin: 0;
	}

	/*
	 * Capped to a measure. Freed from its column the line ran the full width of a
	 * tablet — 90-odd characters for a sentence of eleven, which is a harder read
	 * than the three-column version it replaced.
	 */
	.ph-flow__body {
		grid-area: 2 / 2;
		max-width: 46ch;
		margin-top: 0.3rem;
	}

	/*
	 * Capped, not full-bleed. At the top of this range the frame would run most
	 * of a tablet's width at 132px tall, which is a letterbox rather than a
	 * screen; the cap keeps its proportions close to what the three-column
	 * layout gives it, and phones are narrower than the cap anyway.
	 */
	.ph-flow__mock {
		grid-area: 3 / 2;
		max-width: 30rem;
		margin: 0.85rem 0 0;
	}

	/* The rail, vertical now: badge to badge, clearing both. */
	.ph-flow__step:not(:last-child)::before {
		content: "";
		position: absolute;
		top: var(--flow-n);
		bottom: -1.6rem;
		left: calc(var(--flow-n) / 2);
		width: 1px;
		background: var(--ph-line);
		transform: translateX(-0.5px);
		pointer-events: none;
	}
}

@media (max-width: 48rem) {
	.ph-sec__head {
		align-items: flex-start;
		flex-direction: column;
	}

	/* The tab strip scrolls rather than wrapping into a second row. */
	.ph-tabs {
		width: 100%;
		overflow-x: auto;
		flex-wrap: nowrap;
		scrollbar-width: none;
		/*
		 * Snapping is the affordance. The strip is 478px of chips in 358px of
		 * room, and without it a flick lands mid-chip — which reads as a layout
		 * fault rather than as "there is more to the right".
		 */
		scroll-snap-type: x proximity;
		scroll-padding-left: 0.3rem;
		-webkit-overflow-scrolling: touch;
	}

	.ph-tabs::-webkit-scrollbar { display: none; }

	.ph-tab {
		white-space: nowrap;
		scroll-snap-align: start;
		/* Tighter chips fit two and a half in view, so the third is visibly there. */
		padding: 0.55rem 0.9rem;
	}

	.ph-hero__cta .ph-btn { flex: 1 1 100%; }

	/*
	 * A pill radius needs a pill's proportions. Stacked to four rows this box is
	 * 174px tall, and 999px corners turned it into a stadium whose curve cut into
	 * the first and last lines of its own list.
	 */
	.ph-common {
		padding: 1.1rem 1.25rem;
		border-radius: var(--r-lg);
	}

	.ph-common ul { gap: 0.5rem 1.3rem; }

	/*
	 * The recommended card's overhang only works across a row.
	 *
	 * Stacked, the -0.6rem block margin pulled it up into the card above until
	 * the "most chosen" flag — which hangs 0.72rem past the card's own top edge —
	 * overlapped the monthly plan by 5px, and the -0.2rem inline margin left the
	 * other three cards sitting 3px narrower than it. Both are lateral devices;
	 * in a single column the row gap does the same job honestly.
	 */
	.ph-plans {
		gap: 1.75rem 1rem;
		padding: 1.1rem 0 0.6rem;
	}

	.ph-plan.is-best {
		margin: 0;
		padding: 1.7rem 1.4rem;
	}

	/* The 3rem right gutter was reserving room for a sign that is no longer beside it. */
	.ph-faq__a { padding-right: 0.25rem; }

	/* 38px was under the 44px touch minimum once these became the full card width. */
	.ph-card__btn { padding: 0.7rem 0.9rem; }
}

@media (max-width: 30rem) {
	/*
	 * Two columns put the journal cards at 170px — a headline clamped to two
	 * lines that had room for three words, and a footer where "1 Aug 2026" and
	 * "10 min" each broke over two lines. A review index that cannot show what
	 * was reviewed is worth less than the half page-height it saves.
	 */
	.ph-grid,
	.ph-plans,
	.ph-journal__grid { grid-template-columns: minmax(0, 1fr); }

	/*
	 * 35px set the headline flush to both gutters, so the page had no margin left
	 * to breathe in. The cap keeps the larger phones where they were.
	 */
	.ph-hero__title { font-size: clamp(1.75rem, 8.5vw, 2.2rem); }

	.ph-hero__promises { gap: 0.55rem 0.9rem; }

	.ph-sec__head { margin-bottom: 1.4rem; }

	/*
	 * The savings slot is reserved so four cards keep their rows in step. In one
	 * column there is no row to keep step with, and the two plans that save
	 * nothing were left holding an inch of empty card.
	 */
	.ph-plan__sub { min-height: 0; }
	.ph-plan__sub:empty { margin: 0; }

	.ph-proof > div { padding: 1.05rem 0.9rem; }

	/* 16/10 is a lot of banner once the card runs the full width of the screen. */
	.ph-post__art { aspect-ratio: 16 / 9; }

	/*
	 * At one per row the tile flattened to 358x150 and the mosaic behind it — nine
	 * cells stretched across that band — became stripes rather than products.
	 *
	 * The grid stays at three columns and is NOT widened to four: the shelf art is
	 * exactly nine images, so three columns fill three rows precisely, and a
	 * fourth column leaves the last row three cells short — bare gradient across
	 * the bottom of the tile, which is worse than any amount of letterboxing.
	 *
	 * The height is what fixes the squeeze instead. 14rem puts each cell at
	 * roughly 119x75 — the same 16:10 the product cards crop their artwork to — so
	 * the mosaic reads as a wall of products rather than as stripes.
	 */
	.ph-more { min-height: 14rem; }

	.ph-faq-grid { grid-template-columns: minmax(0, 1fr); }
	.ph-faq-aside { position: static; }
}

@media (prefers-reduced-motion: reduce) {
	.ph .ph-card,
	.ph-card__art img,
	.ph .ph-btn,
	.ph-card__btn { transition: none; }

	.ph .ph-card:hover { transform: none; }
	.ph .ph-card:hover .ph-card__art img { transform: none; }
}


/* generate-style */
blockquote,body,dd,dl,dt,fieldset,figure,h1,h2,h3,h4,h5,h6,hr,html,iframe,legend,li,ol,p,pre,textarea,ul{margin:0;padding:0;border:0}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}progress{vertical-align:baseline}html{box-sizing:border-box}*,::after,::before{box-sizing:inherit}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;margin:0}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-moz-focus-inner{border-style:none;padding:0}:-moz-focusring{outline:1px dotted ButtonText}body,button,input,select,textarea{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-weight:400;text-transform:none;font-size:17px;line-height:1.5}p{margin-bottom:1.5em}h1,h2,h3,h4,h5,h6{font-family:inherit;font-size:100%;font-style:inherit;font-weight:inherit}pre{background:rgba(0,0,0,.05);font-family:inherit;font-size:inherit;line-height:normal;margin-bottom:1.5em;padding:20px;overflow:auto;max-width:100%}blockquote{border-left:5px solid rgba(0,0,0,.05);padding:20px;font-size:1.2em;font-style:italic;margin:0 0 1.5em;position:relative}blockquote p:last-child{margin:0}table,td,th{border:1px solid rgba(0,0,0,.1)}table{border-collapse:separate;border-spacing:0;border-width:1px 0 0 1px;margin:0 0 1.5em;width:100%}td,th{padding:8px}th{border-width:0 1px 1px 0}td{border-width:0 1px 1px 0}hr{background-color:rgba(0,0,0,.1);border:0;height:1px;margin-bottom:40px;margin-top:40px}fieldset{padding:0;border:0;min-width:inherit}fieldset legend{padding:0;margin-bottom:1.5em}h1{font-size:42px;margin-bottom:20px;line-height:1.2em;font-weight:400;text-transform:none}h2{font-size:35px;margin-bottom:20px;line-height:1.2em;font-weight:400;text-transform:none}h3{font-size:29px;margin-bottom:20px;line-height:1.2em;font-weight:400;text-transform:none}h4{font-size:24px}h5{font-size:20px}h4,h5,h6{margin-bottom:20px}ol,ul{margin:0 0 1.5em 3em}ul{list-style:disc}ol{list-style:decimal}li>ol,li>ul{margin-bottom:0;margin-left:1.5em}dt{font-weight:700}dd{margin:0 1.5em 1.5em}b,strong{font-weight:700}cite,dfn,em,i{font-style:italic}address{margin:0 0 1.5em}code,kbd,tt,var{font:15px Monaco,Consolas,"Andale Mono","DejaVu Sans Mono",monospace}abbr,acronym{border-bottom:1px dotted #666;cursor:help}ins,mark{text-decoration:none}sub,sup{font-size:75%;height:0;line-height:0;position:relative;vertical-align:baseline}sup{bottom:1ex}sub{top:.5ex}small{font-size:75%}big{font-size:125%}figure{margin:0}table{margin:0 0 1.5em;width:100%}th{font-weight:700}img{height:auto;max-width:100%}button,input[type=button],input[type=reset],input[type=submit]{background:#55555e;color:#fff;border:1px solid transparent;cursor:pointer;-webkit-appearance:button;padding:10px 20px}input[type=email],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=url],select,textarea{border:1px solid;border-radius:0;padding:10px 15px;max-width:100%}textarea{width:100%}a,button,input{transition:color .1s ease-in-out,background-color .1s ease-in-out}a{text-decoration:none}.button,.wp-block-button .wp-block-button__link{padding:10px 20px;display:inline-block}.wp-block-button .wp-block-button__link{font-size:inherit;line-height:inherit}.using-mouse :focus{outline:0}.using-mouse ::-moz-focus-inner{border:0}.alignleft{float:left;margin-right:1.5em}.alignright{float:right;margin-left:1.5em}.aligncenter{clear:both;display:block;margin:0 auto}.size-auto,.size-full,.size-large,.size-medium,.size-thumbnail{max-width:100%;height:auto}.no-sidebar .entry-content .alignfull{margin-left:calc(-100vw / 2 + 100% / 2);margin-right:calc(-100vw / 2 + 100% / 2);max-width:100vw;width:auto}.screen-reader-text{border:0;clip:rect(1px,1px,1px,1px);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute!important;width:1px;word-wrap:normal!important}.screen-reader-text:focus{background-color:#f1f1f1;border-radius:3px;box-shadow:0 0 2px 2px rgba(0,0,0,.6);clip:auto!important;clip-path:none;color:#21759b;display:block;font-size:.875rem;font-weight:700;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}#primary[tabindex="-1"]:focus{outline:0}.main-navigation{z-index:100;padding:0;clear:both;display:block}.main-navigation a{display:block;text-decoration:none;font-weight:400;text-transform:none;font-size:15px}.main-navigation ul{list-style:none;margin:0;padding-left:0}.main-navigation .main-nav ul li a{padding-left:20px;padding-right:20px;line-height:60px}.inside-navigation{position:relative}.main-navigation .inside-navigation{display:flex;align-items:center;flex-wrap:wrap;justify-content:space-between}.main-navigation .main-nav>ul{display:flex;flex-wrap:wrap;align-items:center}.main-navigation li{position:relative}.main-navigation .menu-bar-items{display:flex;align-items:center;font-size:15px}.main-navigation .menu-bar-items a{color:inherit}.main-navigation .menu-bar-item{position:relative}.main-navigation .menu-bar-item.search-item{z-index:20}.main-navigation .menu-bar-item>a{padding-left:20px;padding-right:20px;line-height:60px}.sidebar .main-navigation .main-nav{flex-basis:100%}.sidebar .main-navigation .main-nav>ul{flex-direction:column}.sidebar .main-navigation .menu-bar-items{margin:0 auto}.sidebar .main-navigation .menu-bar-items .search-item{order:10}.nav-align-center .inside-navigation{justify-content:center}.nav-align-center .main-nav>ul{justify-content:center}.nav-align-right .inside-navigation{justify-content:flex-end}.main-navigation ul ul{display:block;box-shadow:1px 1px 0 rgba(0,0,0,.1);float:left;position:absolute;left:-99999px;opacity:0;z-index:99999;width:200px;text-align:left;top:auto;transition:opacity 80ms linear;transition-delay:0s;pointer-events:none;height:0;overflow:hidden}.main-navigation ul ul a{display:block}.main-navigation ul ul li{width:100%}.main-navigation .main-nav ul ul li a{line-height:normal;padding:10px 20px;font-size:14px}.main-navigation .main-nav ul li.menu-item-has-children>a{padding-right:0;position:relative}.main-navigation.sub-menu-left ul ul{box-shadow:-1px 1px 0 rgba(0,0,0,.1)}.main-navigation.sub-menu-left .sub-menu{right:0}.main-navigation:not(.toggled) ul li.sfHover>ul,.main-navigation:not(.toggled) ul li:hover>ul{left:auto;opacity:1;transition-delay:150ms;pointer-events:auto;height:auto;overflow:visible}.main-navigation:not(.toggled) ul ul li.sfHover>ul,.main-navigation:not(.toggled) ul ul li:hover>ul{left:100%;top:0}.main-navigation.sub-menu-left:not(.toggled) ul ul li.sfHover>ul,.main-navigation.sub-menu-left:not(.toggled) ul ul li:hover>ul{right:100%;left:auto}.nav-float-right .main-navigation ul ul ul{top:0}.menu-item-has-children .dropdown-menu-toggle{display:inline-block;height:100%;clear:both;padding-right:20px;padding-left:10px}.menu-item-has-children ul .dropdown-menu-toggle{padding-top:10px;padding-bottom:10px;margin-top:-10px}.sidebar .menu-item-has-children .dropdown-menu-toggle,nav ul ul .menu-item-has-children .dropdown-menu-toggle{float:right}.widget-area .main-navigation li{float:none;display:block;width:100%;padding:0;margin:0}.sidebar .main-navigation.sub-menu-right ul li.sfHover ul,.sidebar .main-navigation.sub-menu-right ul li:hover ul{top:0;left:100%}.sidebar .main-navigation.sub-menu-left ul li.sfHover ul,.sidebar .main-navigation.sub-menu-left ul li:hover ul{top:0;right:100%}.site-main .comment-navigation,.site-main .post-navigation,.site-main .posts-navigation{margin:0 0 2em;overflow:hidden}.site-main .post-navigation{margin-bottom:0}.paging-navigation .nav-next,.paging-navigation .nav-previous{display:none}.paging-navigation .nav-links>*{padding:0 5px}.paging-navigation .nav-links .current{font-weight:700}.nav-links>:first-child{padding-left:0}.site-header{position:relative}.inside-header{padding:20px 40px}.main-title{margin:0;font-size:25px;line-height:1.2em;word-wrap:break-word;font-weight:700;text-transform:none}.site-description{margin:0;line-height:1.5;font-weight:400;text-transform:none;font-size:15px}.site-logo{display:inline-block;max-width:100%}.site-header .header-image{vertical-align:middle}.inside-header{display:flex;align-items:center}.header-widget{margin-left:auto}.header-widget p:last-child{margin-bottom:0}.nav-float-right .header-widget{margin-left:20px}.nav-float-right #site-navigation{margin-left:auto}.nav-float-left #site-navigation{margin-right:auto;order:-10}.nav-float-left .header-widget{margin-left:0;margin-right:20px;order:-15}.header-aligned-center:not([class*=nav-float-]) .inside-header{justify-content:center;flex-direction:column;text-align:center}.header-aligned-center:not([class*=nav-float-]) .header-widget{margin-left:auto;margin-right:auto}.header-aligned-center:not([class*=nav-float-]) .inside-header>:not(:first-child){margin-top:1em}.header-aligned-right:not([class*=nav-float-]) .inside-header{justify-content:flex-end}.header-aligned-right:not([class*=nav-float-]) .header-widget{margin-right:auto;margin-left:0;order:-10}.site-branding-container{display:inline-flex;align-items:center;text-align:left;flex-shrink:0}.site-branding-container .site-logo{margin-right:1em}.sticky{display:block}.entry-header .gp-icon,.posted-on .updated{display:none}.byline,.entry-header .cat-links,.entry-header .comments-link,.entry-header .tags-links,.group-blog .byline,.single .byline{display:inline}footer.entry-meta .byline,footer.entry-meta .posted-on{display:block}.entry-content:not(:first-child),.entry-summary:not(:first-child),.page-content:not(:first-child){margin-top:2em}.page-links{clear:both;margin:0 0 1.5em}.archive .format-aside .entry-header,.archive .format-status .entry-header,.archive .format-status .entry-meta,.archive .format-status .entry-title,.blog .format-aside .entry-header,.blog .format-status .entry-header,.blog .format-status .entry-meta,.blog .format-status .entry-title{display:none}.archive .format-aside .entry-content,.archive .format-status .entry-content,.blog .format-aside .entry-content,.blog .format-status .entry-content{margin-top:0}.archive .format-status .entry-content p:last-child,.blog .format-status .entry-content p:last-child{margin-bottom:0}.entry-header,.site-content{word-wrap:break-word}.entry-title{margin-bottom:0}.author .page-header .page-title{display:flex;align-items:center}.author .page-header .avatar{margin-right:20px}.page-header .author-info>:last-child,.page-header>:last-child{margin-bottom:0}.entry-meta{font-size:85%;margin-top:.5em;line-height:1.5}footer.entry-meta{margin-top:2em}.cat-links,.comments-link,.tags-links{display:block}.entry-content>p:last-child,.entry-summary>p:last-child,.page-content>p:last-child,.read-more-container,.taxonomy-description p:last-child{margin-bottom:0}.wp-caption{margin-bottom:1.5em;max-width:100%;position:relative}.wp-caption img[class*=wp-image-]{display:block;margin:0 auto 0;max-width:100%}.wp-caption .wp-caption-text{font-size:75%;padding-top:5px;opacity:.8}.wp-caption img{position:relative;vertical-align:bottom}.wp-block-image figcaption{font-size:13px;text-align:center}.wp-block-gallery,ul.blocks-gallery-grid{margin-left:0}.wp-block-gallery .blocks-gallery-image figcaption,.wp-block-gallery .blocks-gallery-item figcaption{background:rgba(255,255,255,.7);color:#000;padding:10px;box-sizing:border-box}.gallery{margin-bottom:1.5em}.gallery-item{display:inline-block;text-align:center;vertical-align:top;width:100%}.gallery-columns-2 .gallery-item{max-width:50%}.gallery-columns-3 .gallery-item{max-width:33.33%}.gallery-columns-4 .gallery-item{max-width:25%}.gallery-columns-5 .gallery-item{max-width:20%}.gallery-columns-6 .gallery-item{max-width:16.66%}.gallery-columns-7 .gallery-item{max-width:14.28%}.gallery-columns-8 .gallery-item{max-width:12.5%}.gallery-columns-9 .gallery-item{max-width:11.11%}.gallery-caption{display:block}.site-main .gallery{margin-bottom:1.5em}.gallery-item img{vertical-align:bottom}.gallery-icon{padding:5px}embed,iframe,object{max-width:100%}.wp-block-post-template{margin-left:0}.widget-area .widget{padding:40px}.widget select{max-width:100%}.footer-widgets .widget :last-child,.sidebar .widget :last-child{margin-bottom:0}.widget-title{margin-bottom:30px;font-size:20px;line-height:1.5;font-weight:400;text-transform:none}.widget ol,.widget ul{margin:0}.widget .search-field{width:100%}.widget .search-form{display:flex}.widget .search-form button.search-submit{font-size:15px}.footer-widgets .widget{margin-bottom:30px}.footer-widgets .widget:last-child,.sidebar .widget:last-child{margin-bottom:0}.widget ul li{list-style-type:none;position:relative;margin-bottom:.5em}.widget ul li ul{margin-left:1em;margin-top:.5em}.wp-calendar-table{table-layout:fixed}.site-content{display:flex}.grid-container{margin-left:auto;margin-right:auto;max-width:1200px}.page-header,.sidebar .widget,.site-main>*{margin-bottom:20px}.both-left .inside-left-sidebar,.both-right .inside-left-sidebar{margin-right:10px}.both-left .inside-right-sidebar,.both-right .inside-right-sidebar{margin-left:10px}.one-container.both-right .site-main,.one-container.right-sidebar .site-main{margin-right:40px}.one-container.both-left .site-main,.one-container.left-sidebar .site-main{margin-left:40px}.one-container.both-sidebars .site-main{margin:0 40px 0 40px}.one-container.archive .post:not(:last-child):not(.is-loop-template-item),.one-container.blog .post:not(:last-child):not(.is-loop-template-item){padding-bottom:40px}.one-container .site-content{padding:40px}.separate-containers .comments-area,.separate-containers .inside-article,.separate-containers .page-header,.separate-containers .paging-navigation{padding:40px}.separate-containers .site-main{margin:20px}.separate-containers.no-sidebar .site-main{margin-left:0;margin-right:0}.separate-containers.both-right .site-main,.separate-containers.right-sidebar .site-main{margin-left:0}.separate-containers.both-left .site-main,.separate-containers.left-sidebar .site-main{margin-right:0}.separate-containers .inside-left-sidebar,.separate-containers .inside-right-sidebar{margin-top:20px;margin-bottom:20px}.inside-page-header{padding:40px}.widget-area .main-navigation{margin-bottom:20px}.one-container .site-main>:last-child,.separate-containers .site-main>:last-child{margin-bottom:0}.full-width-content .container.grid-container{max-width:100%}.full-width-content.no-sidebar.separate-containers .site-main{margin:0}.full-width-content.one-container .site-content,.full-width-content.separate-containers .inside-article{padding:0}.full-width-content .entry-content .alignwide{margin-left:0;width:auto;max-width:unset}.contained-content.one-container .site-content,.contained-content.separate-containers .inside-article{padding:0}.sidebar .grid-container{max-width:100%;width:100%}.both-left .is-left-sidebar,.both-sidebars .is-left-sidebar,.left-sidebar .sidebar{order:-10}.both-left .is-right-sidebar{order:-5}.both-right .is-left-sidebar{order:5}.both-right .is-right-sidebar,.both-sidebars .is-right-sidebar{order:10}.inside-site-info{display:flex;align-items:center;justify-content:center;padding:20px 40px}.site-info{text-align:center;font-size:15px}.post-image:not(:first-child){margin-top:2em}.featured-image{line-height:0}.separate-containers .featured-image{margin-top:20px}.separate-containers .inside-article>.featured-image{margin-top:0;margin-bottom:2em}.one-container .inside-article>.featured-image{margin-top:0;margin-bottom:2em}.gp-icon{display:inline-flex;align-self:center}.gp-icon svg{height:1em;width:1em;top:.125em;position:relative;fill:currentColor}.close-search .icon-search svg:first-child,.icon-menu-bars svg:nth-child(2),.icon-search svg:nth-child(2),.toggled .icon-menu-bars svg:first-child{display:none}.close-search .icon-search svg:nth-child(2),.toggled .icon-menu-bars svg:nth-child(2){display:block}.entry-meta .gp-icon{margin-right:.6em;opacity:.7}nav.toggled .icon-arrow-left svg{transform:rotate(-90deg)}nav.toggled .icon-arrow-right svg{transform:rotate(90deg)}nav.toggled .sfHover>a>.dropdown-menu-toggle .gp-icon svg{transform:rotate(180deg)}nav.toggled .sfHover>a>.dropdown-menu-toggle .gp-icon.icon-arrow-left svg{transform:rotate(-270deg)}nav.toggled .sfHover>a>.dropdown-menu-toggle .gp-icon.icon-arrow-right svg{transform:rotate(270deg)}.container.grid-container{width:auto}.menu-toggle,.mobile-bar-items,.sidebar-nav-mobile{display:none}.menu-toggle{padding:0 20px;line-height:60px;margin:0;font-weight:400;text-transform:none;font-size:15px;cursor:pointer}.menu-toggle .mobile-menu{padding-left:3px}.menu-toggle .gp-icon+.mobile-menu{padding-left:9px}.menu-toggle .mobile-menu:empty{display:none}button.menu-toggle{background-color:transparent;flex-grow:1;border:0;text-align:center}button.menu-toggle:active,button.menu-toggle:focus,button.menu-toggle:hover{background-color:transparent}.has-menu-bar-items button.menu-toggle{flex-grow:0}nav.toggled ul ul.sub-menu{width:100%}.toggled .menu-item-has-children .dropdown-menu-toggle{padding-left:20px}.main-navigation.toggled .main-nav{flex-basis:100%;order:3}.main-navigation.toggled .main-nav>ul{display:block}.main-navigation.toggled .main-nav li{width:100%;text-align:left}.main-navigation.toggled .main-nav ul ul{transition:0s;visibility:hidden;box-shadow:none;border-bottom:1px solid rgba(0,0,0,.05)}.main-navigation.toggled .main-nav ul ul li:last-child>ul{border-bottom:0}.main-navigation.toggled .main-nav ul ul.toggled-on{position:relative;top:0;left:auto!important;right:auto!important;width:100%;pointer-events:auto;height:auto;opacity:1;display:block;visibility:visible;float:none}.main-navigation.toggled .menu-item-has-children .dropdown-menu-toggle{float:right}.mobile-menu-control-wrapper{display:none;margin-left:auto;align-items:center}.has-inline-mobile-toggle #site-navigation.toggled{margin-top:1.5em}.has-inline-mobile-toggle #site-navigation.has-active-search{margin-top:1.5em}.has-inline-mobile-toggle #site-navigation.has-active-search .nav-search-active{position:relative}.has-inline-mobile-toggle #site-navigation.has-active-search .navigation-search input{outline:auto}.nav-float-left .mobile-menu-control-wrapper{order:-10;margin-left:0;margin-right:auto;flex-direction:row-reverse}@media (max-width:768px){.hide-on-mobile{display:none!important}a,body,button,input,select,textarea{transition:all 0s ease-in-out}.inside-header{flex-direction:column;text-align:center}.site-header .header-widget{margin-top:1.5em;margin-left:auto;margin-right:auto;text-align:center}.site-content{flex-direction:column}.container .site-content .content-area{width:auto}.is-left-sidebar.sidebar,.is-right-sidebar.sidebar{width:auto;order:initial}.is-left-sidebar+.is-right-sidebar .inside-right-sidebar{margin-top:0}.both-left .inside-left-sidebar,.both-left .inside-right-sidebar,.both-right .inside-left-sidebar,.both-right .inside-right-sidebar{margin-right:0;margin-left:0}#main{margin-left:0;margin-right:0}body:not(.no-sidebar) #main{margin-bottom:0}.alignleft,.alignright{float:none;display:block;margin-left:auto;margin-right:auto}.comment .children{padding-left:10px;margin-left:0}.entry-meta{font-size:inherit}.entry-meta a{line-height:1.8em}}@media (min-width:769px) and (max-width:1024px){.hide-on-tablet{display:none!important}}@media (min-width:1025px){.hide-on-desktop{display:none!important}}
body{background-color:var(--base-2);color:var(--contrast);}a{color:var(--accent);}a:hover, a:focus, a:active{color:var(--contrast);}.wp-block-group__inner-container{max-width:1200px;margin-left:auto;margin-right:auto;}.site-header .header-image{width:140px;}:root{--contrast:#222222;--contrast-2:#575760;--contrast-3:#b2b2be;--base:#f0f0f0;--base-2:#f7f8f9;--base-3:#ffffff;--accent:#1e73be;}:root .has-contrast-color{color:var(--contrast);}:root .has-contrast-background-color{background-color:var(--contrast);}:root .has-contrast-2-color{color:var(--contrast-2);}:root .has-contrast-2-background-color{background-color:var(--contrast-2);}:root .has-contrast-3-color{color:var(--contrast-3);}:root .has-contrast-3-background-color{background-color:var(--contrast-3);}:root .has-base-color{color:var(--base);}:root .has-base-background-color{background-color:var(--base);}:root .has-base-2-color{color:var(--base-2);}:root .has-base-2-background-color{background-color:var(--base-2);}:root .has-base-3-color{color:var(--base-3);}:root .has-base-3-background-color{background-color:var(--base-3);}:root .has-accent-color{color:var(--accent);}:root .has-accent-background-color{background-color:var(--accent);}.top-bar{background-color:#636363;color:#ffffff;}.top-bar a{color:#ffffff;}.top-bar a:hover{color:#303030;}.site-header{background-color:var(--base-3);}.main-title a,.main-title a:hover{color:var(--contrast);}.site-description{color:var(--contrast-2);}.main-navigation .main-nav ul li a, .main-navigation .menu-toggle, .main-navigation .menu-bar-items{color:var(--contrast);}.main-navigation .main-nav ul li:not([class*="current-menu-"]):hover > a, .main-navigation .main-nav ul li:not([class*="current-menu-"]):focus > a, .main-navigation .main-nav ul li.sfHover:not([class*="current-menu-"]) > a, .main-navigation .menu-bar-item:hover > a, .main-navigation .menu-bar-item.sfHover > a{color:var(--accent);}button.menu-toggle:hover,button.menu-toggle:focus{color:var(--contrast);}.main-navigation .main-nav ul li[class*="current-menu-"] > a{color:var(--accent);}.navigation-search input[type="search"],.navigation-search input[type="search"]:active, .navigation-search input[type="search"]:focus, .main-navigation .main-nav ul li.search-item.active > a, .main-navigation .menu-bar-items .search-item.active > a{color:var(--accent);}.main-navigation ul ul{background-color:var(--base);}.entry-title a{color:var(--contrast);}.entry-title a:hover{color:var(--contrast-2);}.entry-meta{color:var(--contrast-2);}.sidebar .widget{background-color:var(--base-3);}.footer-widgets{background-color:var(--base-3);}.site-info{background-color:var(--base-3);}input[type="text"],input[type="email"],input[type="url"],input[type="password"],input[type="search"],input[type="tel"],input[type="number"],textarea,select{color:var(--contrast);background-color:var(--base-2);border-color:var(--base);}input[type="text"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="password"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="number"]:focus,textarea:focus,select:focus{color:var(--contrast);background-color:var(--base-2);border-color:var(--contrast-3);}button,html input[type="button"],input[type="reset"],input[type="submit"],a.button,a.wp-block-button__link:not(.has-background){color:#ffffff;background-color:#55555e;}button:hover,html input[type="button"]:hover,input[type="reset"]:hover,input[type="submit"]:hover,a.button:hover,button:focus,html input[type="button"]:focus,input[type="reset"]:focus,input[type="submit"]:focus,a.button:focus,a.wp-block-button__link:not(.has-background):active,a.wp-block-button__link:not(.has-background):focus,a.wp-block-button__link:not(.has-background):hover{color:#ffffff;background-color:#3f4047;}a.generate-back-to-top{background-color:rgba( 0,0,0,0.4 );color:#ffffff;}a.generate-back-to-top:hover,a.generate-back-to-top:focus{background-color:rgba( 0,0,0,0.6 );color:#ffffff;}:root{--gp-search-modal-bg-color:var(--base-3);--gp-search-modal-text-color:var(--contrast);--gp-search-modal-overlay-bg-color:rgba(0,0,0,0.2);}@media (max-width:768px){.main-navigation .menu-bar-item:hover > a, .main-navigation .menu-bar-item.sfHover > a{background:none;color:var(--contrast);}}.nav-below-header .main-navigation .inside-navigation.grid-container, .nav-above-header .main-navigation .inside-navigation.grid-container{padding:0px 20px 0px 20px;}.separate-containers .inside-article, .separate-containers .comments-area, .separate-containers .page-header, .separate-containers .paging-navigation, .one-container .site-content, .inside-page-header{padding:0px;}.site-main .wp-block-group__inner-container{padding:0px;}.separate-containers .paging-navigation{padding-top:20px;padding-bottom:20px;}.entry-content .alignwide, body:not(.no-sidebar) .entry-content .alignfull{margin-left:-0px;width:calc(100% + 0px);max-width:calc(100% + 0px);}.one-container.right-sidebar .site-main,.one-container.both-right .site-main{margin-right:0px;}.one-container.left-sidebar .site-main,.one-container.both-left .site-main{margin-left:0px;}.one-container.both-sidebars .site-main{margin:0px;}.sidebar .widget, .page-header, .widget-area .main-navigation, .site-main > *{margin-bottom:0px;}.separate-containers .site-main{margin:0px;}.both-right .inside-left-sidebar,.both-left .inside-left-sidebar{margin-right:0px;}.both-right .inside-right-sidebar,.both-left .inside-right-sidebar{margin-left:0px;}.one-container.archive .post:not(:last-child):not(.is-loop-template-item), .one-container.blog .post:not(:last-child):not(.is-loop-template-item){padding-bottom:0px;}.separate-containers .featured-image{margin-top:0px;}.separate-containers .inside-right-sidebar, .separate-containers .inside-left-sidebar{margin-top:0px;margin-bottom:0px;}.rtl .menu-item-has-children .dropdown-menu-toggle{padding-left:20px;}.rtl .main-navigation .main-nav ul li.menu-item-has-children > a{padding-right:20px;}@media (max-width:768px){.separate-containers .inside-article, .separate-containers .comments-area, .separate-containers .page-header, .separate-containers .paging-navigation, .one-container .site-content, .inside-page-header{padding:30px;}.site-main .wp-block-group__inner-container{padding:30px;}.inside-top-bar{padding-right:30px;padding-left:30px;}.inside-header{padding-right:30px;padding-left:30px;}.widget-area .widget{padding-top:30px;padding-right:30px;padding-bottom:30px;padding-left:30px;}.footer-widgets-container{padding-top:30px;padding-right:30px;padding-bottom:30px;padding-left:30px;}.inside-site-info{padding-right:30px;padding-left:30px;}.entry-content .alignwide, body:not(.no-sidebar) .entry-content .alignfull{margin-left:-30px;width:calc(100% + 60px);max-width:calc(100% + 60px);}.one-container .site-main .paging-navigation{margin-bottom:0px;}}/* End cached CSS */.is-right-sidebar{width:30%;}.is-left-sidebar{width:30%;}.site-content .content-area{width:100%;}@media (max-width:768px){.main-navigation .menu-toggle,.sidebar-nav-mobile:not(#sticky-placeholder){display:block;}.main-navigation ul,.gen-sidebar-nav,.main-navigation:not(.slideout-navigation):not(.toggled) .main-nav > ul,.has-inline-mobile-toggle #site-navigation .inside-navigation > *:not(.navigation-search):not(.main-nav){display:none;}.nav-align-right .inside-navigation,.nav-align-center .inside-navigation{justify-content:space-between;}}
.dynamic-author-image-rounded{border-radius:100%;}.dynamic-featured-image, .dynamic-author-image{vertical-align:middle;}.one-container.blog .dynamic-content-template:not(:last-child), .one-container.archive .dynamic-content-template:not(:last-child){padding-bottom:0px;}.dynamic-entry-excerpt > p:last-child{margin-bottom:0px;}
.post-image:not(:first-child), .page-content:not(:first-child), .entry-content:not(:first-child), .entry-summary:not(:first-child), footer.entry-meta{margin-top:0em;}.post-image-above-header .inside-article div.featured-image, .post-image-above-header .inside-article div.post-image{margin-bottom:0em;}

/* generate-child */
/*
Theme Name: GeneratePress Child
Theme URI:  https://puregpl.com/
Description: Child theme for GeneratePress
Author: Varun Haldhar
Author URI: https://puregpl.com/
Template: generatepress
Version: 1.0.0
Text Domain: generatepress-child
*/

/* You can add custom CSS below this line */

:root {
	/* Neutrals */
	--white: #FFFFFF;
	--gray-50: #F9FAFB;
	--gray-100: #F3F4F6;
	--gray-200: #E5E7EB;
	--gray-300: #D1D5DB;
	--gray-600: #4B5563;
	--gray-700: #374151;
	--gray-900: #111827;

	/* Gradients */
	--gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
	--gradient-gold: linear-gradient(135deg, #FFB800 0%, #FF8C00 100%);
	--gradient-emerald: linear-gradient(135deg, #06B6D4 0%, #0891B2 100%);
	--gradient-hero: linear-gradient(135deg, #1a0b2e 0%, #6B46C1 50%, #9333EA 100%);
	--gradient-pink: linear-gradient(135deg, #EC4899 0%, #F472B6 100%);

	/* Typography */
	--font-display: 'Inter', -apple-system, system-ui, sans-serif;

	/* Spacing */
	--spacing-xs: 0.5rem;
	--spacing-sm: 1rem;
	--spacing-md: 1.5rem;
	--spacing-lg: 2rem;
	--spacing-xl: 3rem;
	--spacing-2xl: 4rem;
	--spacing-3xl: 6rem;

	/* Effects */
	--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
	--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
	--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
	--shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.15);
	--shadow-2xl: 0 25px 50px rgba(0, 0, 0, 0.25);

	/* Animations */
	--transition-fast: 0.15s ease;
	--transition-base: 0.3s ease;
	--transition-smooth: 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

/* pgpl-chrome */
/**
 * PureGPL — site chrome.
 *
 * "Ultramarine Ledger", the same tokens as checkout.css and receipt.css, so the
 * header a buyer sees on the homepage is the header they see at checkout.
 *
 * Tokens are declared on :root here rather than on a wrapper, because the
 * header and footer are two separate elements at opposite ends of the document.
 */

:root {
	--pgpl-ink: #0f1222;
	--pgpl-ink-soft: #3d4260;
	--pgpl-muted: #6a7091;
	--pgpl-paper: #fcfcfa;
	--pgpl-surface: #fff;
	--pgpl-line: #dde0ec;
	--pgpl-line-strong: #c3c8dd;
	--pgpl-ultra: #2436e4;
	--pgpl-ultra-deep: #1b29b8;
	--pgpl-wash: #eef1ff;
	--pgpl-night: #10132a;
	--pgpl-night-soft: #1b2040;
	/* Aurora surfaces: a near-black utility strip over a deep navy command bar. */
	--pgpl-aurora: #0b0e1c;
	--pgpl-aurora-deep: #070915;
	--pgpl-aurora-panel: #0f1324;
	--pgpl-glow: rgba(108, 134, 255, 0.5);
}

/* ---------------------------------------------------------------------------
 * Header
 * ------------------------------------------------------------------------ */

/*
 * "Aurora Rail" — the header is a dark surface with one soft light source.
 *
 * Everything inside inherits a light colour from here, which is what lets the
 * wordmark, the actions and the drawer share markup with the light footer
 * without a single duplicated element.
 */
.pgpl-hd {
	position: sticky;
	top: 0;
	z-index: 200;
	color: rgba(255, 255, 255, 0.82);
	background: var(--pgpl-aurora);
	border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}

/*
 * The admin bar is position:fixed and would sit on top of a sticky header.
 * WordPress only adds this class when the bar is actually showing.
 *
 * All three of its states have to be matched, because the bar changes both
 * height and positioning scheme as the viewport narrows. With only the 32px
 * desktop offset, a logged-in editor got a 14px overlap between 601 and 782px
 * — where the bar is 46px — and, below 600px where the bar stops being fixed
 * and scrolls away, a permanent 32px hole above the header.
 */
.admin-bar .pgpl-hd {
	top: 32px;
}

@media screen and (max-width: 782px) {
	.admin-bar .pgpl-hd {
		top: 46px;
	}
}

@media screen and (max-width: 600px) {
	.admin-bar .pgpl-hd {
		top: 0;
	}
}

.pgpl-hd *,
.pgpl-hd *::before,
.pgpl-hd *::after,
.pgpl-drawer *,
.pgpl-ft *,
.pgpl-ft *::before,
.pgpl-ft *::after {
	box-sizing: border-box;
}

/*
 * ---------------------------------------------------------------------------
 * Link-colour guard  —  read this before adding any anchor to the chrome
 * ---------------------------------------------------------------------------
 *
 * GeneratePress ships `a:hover, a:focus, a:active { color: var(--contrast) }`
 * inline. On this site --contrast is #222, so EVERY link in the chrome turns
 * near-black on hover unless something outruns that rule.
 *
 * Its specificity is (0,1,1) — one pseudo-class plus one element — which quietly
 * beats a plain single-class selector like `.pgpl-drawer__updates` at (0,1,0).
 * It caught the header logo, two drawer controls, the footer wordmark, and most
 * recently the drawer's changelog chip, whose label dropped to 1.03:1 against
 * its own background while the timestamp beside it stayed lit, because that
 * span happened to carry its own colour.
 *
 * Patching each anchor as it surfaced was the wrong approach: the next one added
 * to this file would simply have been the fifth. This guard covers the whole of
 * the chrome at (0,2,1) — enough to beat GeneratePress, and low enough that any
 * component rule using two classes still wins and can choose its own colour.
 *
 * White is the correct default here: the chrome is dark everywhere it renders.
 *
 * Placed EARLY on purpose. A handful of existing rules — `.pgpl-hd__col-list
 * a:hover`, for one — tie this at (0,2,1), and on a tie the later rule wins.
 * Moving this block down the file would silently take those overrides away.
 *
 * `:visited` is deliberately NOT in this list, and must not be added back.
 * GeneratePress only forces a colour on :hover/:focus/:active, so :visited was
 * never being defended against — it was volunteering, and at (0,2,1) it outranked
 * every component that sets its own resting colour. Two of them are WHITE
 * surfaces: the active currency pill and the "See plans" button both went white
 * text on white and disappeared the moment their URL had been visited. It also
 * lit every visited link in the drawer and footer to full white while unvisited
 * siblings sat at 50-78%, so visited rows read as "you are here" and drowned out
 * the real `is-current` marker. Author colours already beat the browser's own
 * :visited style, so removing this costs nothing.
 */
.pgpl-hd a:hover,
.pgpl-hd a:focus,
.pgpl-hd a:active,
.pgpl-drawer a:hover,
.pgpl-drawer a:focus,
.pgpl-drawer a:active,
.pgpl-ft a:hover,
.pgpl-ft a:focus,
.pgpl-ft a:active {
	color: #fff;
}

.pgpl-hd__wrap {
	display: flex;
	gap: 1rem;
	align-items: center;
	max-width: 1240px;
	margin: 0 auto;
	padding: 0 max(1rem, env(safe-area-inset-left));
}

.pgpl-hd__icon {
	flex: 0 0 auto;
}

/* --- Utility band --------------------------------------------------------- */

/* Darker than the command bar, so it reads as a sub-band rather than a stripe. */
.pgpl-hd__utility {
	color: rgba(255, 255, 255, 0.62);
	background: var(--pgpl-aurora-deep);
	border-bottom: 1px solid rgba(255, 255, 255, 0.06);
	font-size: 0.8rem;
}

.pgpl-hd__utility .pgpl-hd__wrap {
	/* Left-packed with the right cluster pushed across, rather than
	   space-between: with a second pill on the left, space-between parked it
	   in the middle of the band on its own. */
	justify-content: flex-start;
	gap: 0.6rem;
	min-height: 2.25rem;
}

/*
 * The changelog link, as a status chip rather than a line of grey text.
 *
 * It was the least visible thing in the header despite pointing at the one page
 * that answers "is this store alive?" — the question every GPL buyer has. A
 * bordered chip with a live dot and a real timestamp answers it before the
 * click.
 */
.pgpl-hd__updates {
	display: inline-flex;
	gap: 0.5rem;
	align-items: center;
	padding: 0.28rem 0.7rem 0.28rem 0.6rem;
	color: rgba(255, 255, 255, 0.85);
	text-decoration: none;
	background: rgba(255, 255, 255, 0.06);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: 999px;
	transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}

.pgpl-hd .pgpl-hd__updates:hover,
.pgpl-hd .pgpl-hd__updates:focus {
	color: #fff;
	background: rgba(255, 255, 255, 0.12);
	border-color: rgba(255, 255, 255, 0.22);
}

.pgpl-hd__updates-label {
	font-weight: 600;
}

/* The timestamp is supporting detail; it must not compete with the label. */
.pgpl-hd__updates-when {
	padding-left: 0.5rem;
	color: rgba(255, 255, 255, 0.5);
	border-left: 1px solid rgba(255, 255, 255, 0.14);
}

.pgpl-hd__updates-arrow {
	transition: transform 0.16s ease;
}

.pgpl-hd__updates:hover .pgpl-hd__updates-arrow,
.pgpl-hd__updates:focus .pgpl-hd__updates-arrow {
	transform: translateX(2px);
}

/* --- The live dot --------------------------------------------------------- */

.pgpl-hd__pulse {
	position: relative;
	flex: 0 0 7px;
	width: 7px;
	height: 7px;
	background: #4ade80;
	border-radius: 50%;
}

/*
 * The halo is a separate ::after so only IT animates. Pulsing the dot itself
 * would move the text beside it on every cycle.
 */
.pgpl-hd__pulse::after {
	content: "";
	position: absolute;
	inset: -3px;
	background: rgba(74, 222, 128, 0.45);
	border-radius: 50%;
	animation: pgpl-pulse 2.4s ease-out infinite;
}

@keyframes pgpl-pulse {
	0%   { transform: scale(0.6); opacity: 0.8; }
	70%  { transform: scale(1.5); opacity: 0; }
	100% { transform: scale(1.5); opacity: 0; }
}

/*
 * A dot that pulses forever is exactly the kind of persistent motion that
 * triggers vestibular symptoms. Reduced motion gets a static halo — the state
 * is still legible, it simply stops moving.
 */
@media (prefers-reduced-motion: reduce) {
	.pgpl-hd__pulse::after {
		animation: none;
		opacity: 0.35;
	}
}

/*
 * There is no narrow-phone rule for the timestamp, and there cannot usefully be
 * one: a `@media (max-width: 30rem)` block used to hide .pgpl-hd__updates-when
 * here, but the entire utility band is already `display: none` from 60rem down,
 * so it could never once have applied. The drawer carries the freshness chip on
 * phones instead, under its own class.
 */

/* The announcement: the pill beside "Latest updates", almost its twin — a
   shade lighter ink, green text and a solid green tag. The green is the live
   dot's, which the band already uses to mean "something is fresh here", so
   the pill borrows a meaning the header has taught rather than adding a
   colour. Findable, not loud. */
.pgpl-hd__announce {
	display: inline-flex;
	gap: 0.5rem;
	align-items: center;
	padding: 0.28rem 0.7rem 0.28rem 0.4rem;
	color: #a9f5c3;
	text-decoration: none;
	background: #141a3d;
	border: 1px solid rgba(74, 222, 128, 0.35);
	border-radius: 999px;
	transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}
.pgpl-hd .pgpl-hd__announce:hover,
.pgpl-hd .pgpl-hd__announce:focus {
	color: #d2fbe0;
	background: #1a2150;
	border-color: rgba(74, 222, 128, 0.6);
}
.pgpl-hd__announce-tag {
	padding: 0.1rem 0.4rem;
	background: #4ade80;
	color: #052e16;
	border-radius: 5px;
	font-size: 0.62rem;
	font-weight: 800;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	line-height: 1.4;
}
.pgpl-hd__announce-label { font-weight: 600; }
.pgpl-hd__announce .pgpl-hd__updates-arrow { opacity: 0.8; }

/* The same thing in the phone drawer, where the band does not exist. Both
   classes, because the plain row rule is declared later in this file and won
   the tie on background. */
.pgpl-drawer__updates.pgpl-drawer__announce {
	margin-bottom: 0.5rem;
	color: #a9f5c3;
	background: #141a3d;
	border-color: rgba(74, 222, 128, 0.35);
}
.pgpl-drawer__updates.pgpl-drawer__announce .pgpl-drawer__updates-label { color: #a9f5c3; }

.pgpl-hd__utility-right {
	display: flex;
	gap: 0.9rem;
	align-items: center;
	margin-left: auto;
}

.pgpl-hd__count strong {
	color: #fff;
	font-variant-numeric: tabular-nums;
}

.pgpl-hd__currency {
	display: inline-flex;
	gap: 2px;
	padding: 2px;
	background: rgba(255, 255, 255, 0.1);
	border-radius: 999px;
}

.pgpl-hd__chip {
	padding: 0.2rem 0.65rem;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.03em;
	color: rgba(255, 255, 255, 0.75);
	text-decoration: none;
	border-radius: 999px;
	transition: background-color 0.15s ease, color 0.15s ease;
}

.pgpl-hd__chip:hover,
.pgpl-hd__chip:focus {
	color: #fff;
}

/* ...but never on the active pill, which is white. */
.pgpl-hd__chip.is-active:hover,
.pgpl-hd__chip.is-active:focus {
	color: var(--pgpl-ink);
}

.pgpl-hd__chip.is-active {
	color: var(--pgpl-ink);
	background: #fff;
}

/* --- Command band --------------------------------------------------------- */

/*
 * Taller than a normal header row on purpose. This band IS the navigation now,
 * and the search field inside it has to read as the primary control rather than
 * as one more thing wedged between the logo and the account links.
 */
.pgpl-hd__command {
	position: relative;
}

/*
 * The clip lives on the glow's own layer, not on the band.
 *
 * `overflow: hidden` here was containing the decoration below — and clipping
 * every absolutely positioned descendant with it, including Ajax Search Pro's
 * floating results panel, which renders as an overlay beneath the field. The
 * suggestions were being cut off at the bottom edge of the band, on the one
 * control this entire header is built around.
 */
.pgpl-hd__glow {
	position: absolute;
	inset: 0;
	overflow: hidden;
	pointer-events: none;
}

/*
 * The aurora. ONE light source, top-right, at low opacity — a single soft glow
 * reads as atmosphere; two or more read as a gradient mesh, which dates fast
 * and fights everything placed on top of it.
 *
 * `padding-top` rather than `aspect-ratio`: the height has to come from the
 * width either way, and on a browser without aspect-ratio support this element
 * is the only thing painting the glow — it would collapse to nothing.
 */
.pgpl-hd__glow::after {
	content: "";
	position: absolute;
	top: -320%;
	right: -6%;
	width: 46%;
	height: 0;
	padding-top: 46%;
	background: radial-gradient(circle, var(--pgpl-glow) 0%, rgba(108, 134, 255, 0) 66%);
	pointer-events: none;
}

.pgpl-hd__command .pgpl-hd__wrap {
	position: relative;
	z-index: 1;
	min-height: 5rem;
	gap: 1.25rem;
}

.pgpl-hd__brand {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	text-decoration: none;
}

/*
 * Ajax Search Pro renders its own markup and is deliberately left alone —
 * restyling a search plugin's internals from the outside breaks on its next
 * update. Only the container is sized.
 */
.pgpl-hd__search {
	position: relative;
	flex: 1 1 auto;
	min-width: 0;
}

.pgpl-hd__search > * {
	max-width: none;
}

/*
 * A WHITE field on the dark bar, not a glass one.
 *
 * This used to be scoped to an Ajax Search Pro variant, because ASP rendered its
 * own input with no surface of its own while the fallback form brought one — and
 * painting both nested a white box inside a grey one. ASP is gone; the form below
 * is the only search there is, so it simply IS the field.
 *
 * White rather than glass because it makes search the brightest object in a dark
 * bar, which is where the emphasis belongs on a shop whose catalogue is too large
 * to browse.
 */
/*
 * A pill, like everything else in this bar.
 *
 * The field used to be a 12px rectangle sitting between a 999px Browse pill and
 * two 999px action pills — the only squared object in a header built entirely
 * from round ones, which read as unfinished rather than deliberate. Matching the
 * radius costs nothing and makes the bar look designed rather than assembled.
 *
 * Depth comes from two soft layers instead of one heavy drop: a hairline that
 * defines the edge against the dark bar, and a wide, very soft shadow that lifts
 * it. A single strong shadow reads as a sticker; two quiet ones read as glass on
 * a surface.
 */
.pgpl-hd__fallback {
	position: relative;
	display: flex;
	gap: 0.6rem;
	align-items: center;
	max-width: none;
	padding: 0 0.3rem 0 1.15rem;
	background: #fff;
	border: 0;
	border-radius: 999px;
	box-shadow:
		0 1px 2px rgba(11, 14, 28, 0.16),
		0 14px 30px -18px rgba(0, 0, 0, 0.8);
	transition: box-shadow 0.18s ease;
}

.pgpl-hd__fallback:focus-within {
	box-shadow:
		0 0 0 3px rgba(108, 134, 255, 0.42),
		0 1px 2px rgba(11, 14, 28, 0.16),
		0 14px 30px -18px rgba(0, 0, 0, 0.8);
}

/*
 * The LEADING icon only — note the child combinator.
 *
 * The submit button carries the same icon class, so a descendant selector here
 * tints that one too: at rest it went muted grey on ultramarine, and on focus it
 * turned ultramarine on ultramarine and disappeared entirely. The button owns
 * its own colour and must keep it.
 */
.pgpl-hd__fallback > .pgpl-hd__icon {
	color: var(--pgpl-muted);
	transition: color 0.18s ease;
}

.pgpl-hd__fallback:focus-within > .pgpl-hd__icon {
	color: var(--pgpl-ultra);
}

.pgpl-hd__fallback input[type="search"] {
	flex: 1 1 auto;
	min-width: 0;
	height: 3.1rem;
	padding: 0;
	font-family: inherit;
	font-size: 0.95rem;
	color: var(--pgpl-ink);
	background: transparent;
	border: 0;
	outline: none;
	box-shadow: none;
	-webkit-appearance: none;
	appearance: none;
}

/* Chrome draws its own clear button on type=search; it collides with ours. */
.pgpl-hd__fallback input[type="search"]::-webkit-search-decoration,
.pgpl-hd__fallback input[type="search"]::-webkit-search-cancel-button {
	-webkit-appearance: none;
}

.pgpl-hd__fallback input[type="search"]::placeholder {
	color: var(--pgpl-muted);
	opacity: 1;
}

/* --- The keyboard hint ---------------------------------------------------- */

/*
 * Quiet by default and gone the moment it stops being useful.
 *
 * It is an affordance, not a control: it should be findable by someone looking
 * for it and invisible to everyone else. So it sits at the muted end of the
 * palette, and it leaves as soon as the field is focused — at which point the
 * shortcut has already done its job and the hint is just something in the way of
 * what you are typing.
 */
.pgpl-hd__kbd {
	flex: 0 0 auto;
	padding: 0.24rem 0.5rem;
	font-family: inherit;
	font-size: 0.68rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	/*
	 * Not --pgpl-muted. At 10.9px on this 5%-ink chip that token measures
	 * 4.36:1 — under the 4.5 WCAG asks of small text, and axe flags it. The
	 * chip is meant to be quiet, but quiet has a floor.
	 */
	color: #54597a;
	background: rgba(11, 14, 28, 0.05);
	border: 1px solid rgba(11, 14, 28, 0.08);
	border-radius: 7px;
	white-space: nowrap;
	transition: opacity 0.15s ease;
}

.pgpl-hd__fallback:focus-within .pgpl-hd__kbd {
	opacity: 0;
	pointer-events: none;
}

/*
 * No modifier key on a touch screen, so no hint. Gated on the pointer rather
 * than on width: a tablet with a keyboard is still a keyboard.
 */
@media (hover: none), (pointer: coarse) {
	.pgpl-hd__kbd {
		display: none;
	}
}

/* --- Submit --------------------------------------------------------------- */

/*
 * A circle inside a pill, inset evenly on all four sides.
 *
 * The plugin this replaces sat its button 5px from the top and bottom of the
 * field but 1px from the right edge, at a 9px radius inside a 12px one — three
 * mismatches that together made it look dropped in rather than built in.
 */
.pgpl-hd__go {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	width: 2.5rem;
	height: 2.5rem;
	color: #fff;
	cursor: pointer;
	background: var(--pgpl-ultra);
	border: 0;
	border-radius: 999px;
	transition: background-color 0.15s ease, transform 0.12s ease;
}

@media (hover: hover) and (pointer: fine) {
	.pgpl-hd__go:hover {
		background: var(--pgpl-ultra-deep);
	}
}

.pgpl-hd__go:active {
	transform: scale(0.94);
}

.pgpl-hd__go:focus-visible {
	outline: 2px solid var(--pgpl-ultra);
	outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
	.pgpl-hd__go:active {
		transform: none;
	}
}

/* --- Actions -------------------------------------------------------------- */

.pgpl-hd__actions {
	display: flex;
	flex: 0 0 auto;
	gap: 0.35rem;
	align-items: center;
}

.pgpl-hd__action {
	position: relative;
	display: inline-flex;
	gap: 0.4rem;
	align-items: center;
	padding: 0.5rem 0.7rem;
	font-size: 0.85rem;
	font-weight: 600;
	color: rgba(255, 255, 255, 0.85);
	text-decoration: none;
	/*
	 * Fully rounded, which resolves to a pill on desktop (where the control
	 * carries a label) and a circle on mobile (where it is a 42px square holding
	 * an 18px icon). The old 9px corners made these the only squared controls in
	 * a header built from 999px pills and 12-14px cards — beside the Browse
	 * button's pill they read as unfinished rather than deliberate.
	 */
	border-radius: 999px;
	transition: background-color 0.15s ease, color 0.15s ease, transform 0.1s ease;
}

/*
 * Hover is for pointers only.
 *
 * On a touch screen there is no "unhover": tapping an icon latches :hover and
 * the highlight stays painted until something else is tapped. Combined with
 * :focus doing the same thing, two icons could sit lit at once — which is what
 * made the bar look broken. Gating on `hover: hover` means a phone never enters
 * the state at all.
 */
@media (hover: hover) and (pointer: fine) {
	.pgpl-hd__action:hover {
		color: #fff;
		background: rgba(255, 255, 255, 0.07);
	}
}

/* Keyboard focus still needs to be visible — but not a mere tap. */
.pgpl-hd__action:focus-visible {
	color: #fff;
	background: rgba(255, 255, 255, 0.07);
}

/*
 * Touch feedback: a press that ends when the finger lifts. This is what :hover
 * was standing in for on mobile, without the part where it gets stuck.
 */
.pgpl-hd__action:active {
	background: rgba(255, 255, 255, 0.13);
	transform: scale(0.94);
}

.pgpl-hd__badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 1.15rem;
	height: 1.15rem;
	padding: 0 0.3rem;
	font-size: 0.68rem;
	font-weight: 700;
	line-height: 1;
	color: #fff;
	background: var(--pgpl-ultra);
	border-radius: 999px;
	font-variant-numeric: tabular-nums;
}

/*
 * Lifted out of the flow, which is what the `position: relative` on
 * .pgpl-hd__action was always for — that rule sat there for months with nothing
 * positioned against it.
 *
 * In flow the badge is a third flex child, and on mobile the action collapses to
 * a 42px square with `padding: 0`: an 18px icon plus a 6.4px gap plus an 18.4px
 * badge is 42.8px of content in a 42px box before the count even reaches two
 * digits, so it burst its own circle and crowded the burger beside it.
 */
/*
 * On desktop the badge stays IN FLOW — a third flex child after the label, so
 * the control reads "cart · Cart · (1)" on one line. It is lifted out of the
 * flow only on mobile, in the narrow-screen block near the end of this file,
 * where the label is clipped and the control is a 44px square. Pinning it at
 * every width put a filled circle on top of the word "Cart".
 */

/*
 * On the drawer's solid CTA the badge was ultramarine on ultramarine — the same
 * token for both — so the pill vanished and the count read as loose white text
 * beside the word "Cart". White pill, blue number: the same object, inverted.
 */
.pgpl-drawer__btn--solid .pgpl-hd__badge {
	color: var(--pgpl-ultra-deep);
	background: #fff;
}

.pgpl-hd__burger {
	display: none;
	align-items: center;
	justify-content: center;
	width: 2.5rem;
	height: 2.5rem;
	color: #fff;
	cursor: pointer;
	background: transparent;
	border: 0;
	border-radius: 999px;
	transition: background-color 0.15s ease, transform 0.1s ease;
}

@media (hover: hover) and (pointer: fine) {
	.pgpl-hd__burger:hover {
		color: #fff;
		background: rgba(255, 255, 255, 0.07);
	}
}

.pgpl-hd__burger:focus-visible {
	background: rgba(255, 255, 255, 0.07);
}

.pgpl-hd__burger:active {
	background: rgba(255, 255, 255, 0.13);
	transform: scale(0.94);
}

/* --- Account menu --------------------------------------------------------- */

/*
 * The signed-in dropdown.
 *
 * It escapes the command band, which it could not have done before the aurora
 * glow was moved onto its own clipping layer — the band used to carry
 * `overflow: hidden` and would have sliced this panel off at its bottom edge,
 * the same way it was slicing the search suggestions.
 */
.pgpl-hd__acct {
	position: relative;
	flex: 0 0 auto;
}

/*
 * The phone's copy of the Account control, hidden wherever the dropdown shows.
 * Two elements rather than one that changes role at a breakpoint: a link and a
 * disclosure are different things, and `display: none` keeps whichever is not
 * in play out of the accessibility tree entirely.
 */
.pgpl-hd__action--compact {
	display: none;
}

.pgpl-hd__acct-toggle {
	cursor: pointer;
	background: none;
	border: 0;
	font-family: inherit;
	font-size: 0.85rem;
	font-weight: 600;
}

.pgpl-hd__acct-toggle svg:last-child {
	width: 14px;
	height: 14px;
	opacity: 0.6;
	transition: transform 0.18s ease;
}

.pgpl-hd__acct-toggle[aria-expanded="true"] svg:last-child {
	transform: rotate(180deg);
}

/*
 * The initials chip, which is what makes this read as "you" rather than as one
 * more icon. Ultramarine so it belongs to the brand, and the only saturated
 * object in the bar apart from the search button.
 */
.pgpl-hd__acct-chip {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	font-size: 0.68rem;
	font-weight: 800;
	letter-spacing: 0.02em;
	color: #fff;
	background: linear-gradient(150deg, var(--pgpl-ultra), var(--pgpl-ultra-deep));
	border-radius: 9px;
}

.pgpl-hd__acct-chip--lg {
	width: 40px;
	height: 40px;
	font-size: 0.95rem;
	border-radius: 12px;
}

.pgpl-hd__acct-menu[hidden] {
	display: none;
}

.pgpl-hd__acct-menu {
	position: absolute;
	top: calc(100% + 10px);
	right: 0;
	z-index: 40;
	/*
	 * Sized to what is in it, within bounds.
	 *
	 * A flat 19rem was set while the membership badge still shared the identity
	 * row; once that went, the widest thing in here measured 201px inside a
	 * 304px panel — ninety pixels of empty right-hand side that made the menu
	 * look unfinished. max-content lets the address decide the width, the floor
	 * stops a short name collapsing it to a sliver, and the ceiling both caps a
	 * long address (which then ellipses, as it already did) and keeps the panel
	 * on screen at any viewport.
	 */
	width: max-content;
	min-width: 14rem;
	max-width: min(20rem, calc(100vw - 2rem));
	padding: 0.45rem;
	background: var(--pgpl-aurora-panel);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: 18px;
	/* Two shadows: a hairline lift that separates it from the bar, and a long
	   soft one that puts it convincingly in front of the page. */
	box-shadow:
		0 1px 0 rgba(255, 255, 255, 0.06) inset,
		0 28px 60px -22px rgba(0, 0, 0, 0.85);
	opacity: 0;
	transform: translateY(-6px);
	transition: opacity 0.18s ease, transform 0.18s ease;
}

.pgpl-hd__acct-menu.is-open {
	opacity: 1;
	transform: translateY(0);
}

/* --- Identity row --------------------------------------------------------- */

.pgpl-hd__acct-id {
	display: flex;
	gap: 0.65rem;
	align-items: center;
	padding: 0.7rem 0.7rem 0.85rem;
	border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.pgpl-hd__acct-id-text {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	gap: 0.15rem;
	min-width: 0;
}

.pgpl-hd__acct-id-text strong {
	font-size: 0.9rem;
	font-weight: 700;
	color: #fff;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

/* An address is long and is not the point — it confirms which account this is. */
.pgpl-hd__acct-mail {
	font-size: 0.75rem;
	color: rgba(255, 255, 255, 0.62);
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

/* --- Menu rows ------------------------------------------------------------ */

/* The divider lives on the list, not on the log-out row — a border there would
   sit inside that row's own hover pill and read as a seam across it. */
.pgpl-hd__acct-nav ul {
	margin: 0.45rem 0;
	padding: 0 0 0.45rem;
	list-style: none;
	border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.pgpl-hd__acct-nav a,
.pgpl-hd__acct-out {
	display: flex;
	gap: 0.65rem;
	align-items: center;
	min-height: 40px;
	padding: 0 0.7rem;
	font-size: 0.86rem;
	font-weight: 600;
	color: rgba(255, 255, 255, 0.82);
	text-decoration: none;
	border-radius: 11px;
	transition: color 0.15s ease, background-color 0.15s ease;
}

.pgpl-hd__acct-nav a svg,
.pgpl-hd__acct-out svg {
	flex: 0 0 auto;
	opacity: 0.72;
}

/*
 * Gated on pointer type, like everything else in this file that highlights:
 * a tap on a touch screen has no "unhover" and would leave a row lit.
 */
@media (hover: hover) and (pointer: fine) {
	.pgpl-hd .pgpl-hd__acct-nav a:hover,
	.pgpl-hd .pgpl-hd__acct-out:hover {
		color: #fff;
		background: rgba(255, 255, 255, 0.08);
	}
}

.pgpl-hd .pgpl-hd__acct-nav a:focus-visible,
.pgpl-hd .pgpl-hd__acct-out:focus-visible {
	color: #fff;
	background: rgba(255, 255, 255, 0.08);
}

.pgpl-hd .pgpl-hd__acct-nav a:active,
.pgpl-hd .pgpl-hd__acct-out:active {
	background: rgba(255, 255, 255, 0.13);
}

/*
 * Log out sits below a rule and reads cooler than the navigation above it. It
 * is the one item here that ends the session rather than going somewhere, and
 * it should not be the thing a hurried cursor lands on by accident.
 */
.pgpl-hd__acct-out {
	color: rgba(255, 255, 255, 0.62);
}

.pgpl-hd__acct-out svg {
	opacity: 0.6;
}

/* --- Browse button + panel ------------------------------------------------ */

.pgpl-hd__browse {
	display: inline-flex;
	gap: 0.4rem;
	align-items: center;
	padding: 0.55rem 0.95rem;
	font-family: inherit;
	font-size: 0.85rem;
	font-weight: 700;
	color: rgba(255, 255, 255, 0.9);
	cursor: pointer;
	background: rgba(255, 255, 255, 0.09);
	border: 1px solid rgba(255, 255, 255, 0.16);
	border-radius: 999px;
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.pgpl-hd__browse:hover {
	color: #fff;
	background: rgba(255, 255, 255, 0.16);
}

/* Inverted while open, so the button reads as part of the panel it controls. */
.pgpl-hd__browse[aria-expanded="true"] {
	color: var(--pgpl-aurora);
	background: #fff;
	border-color: #fff;
}

/* The chevron flips to point at the panel it opened. */
.pgpl-hd__browse svg:last-child {
	transition: transform 0.18s ease;
}

.pgpl-hd__browse[aria-expanded="true"] svg:last-child {
	transform: rotate(180deg);
}

.pgpl-hd__panel[hidden] {
	display: none;
}

/* The panel continues the bar's surface — a white sheet under a dark bar reads
   as a different component that happened to open, not as the bar extending. */
.pgpl-hd__panel {
	border-top: 1px solid rgba(255, 255, 255, 0.07);
	background: var(--pgpl-aurora-panel);
	box-shadow: 0 30px 50px -30px rgba(0, 0, 0, 0.9);
	/* Animated open; the [hidden] attribute is removed a frame earlier by JS. */
	opacity: 0;
	transform: translateY(-6px);
	transition: opacity 0.18s ease, transform 0.18s ease;
}

.pgpl-hd__panel.is-open {
	opacity: 1;
	transform: translateY(0);
}

.pgpl-hd__panel .pgpl-hd__wrap {
	display: block;
}

.pgpl-hd__panel-grid {
	display: grid;
	/* Wider minimum: 10rem let six tracks form for four columns, and the two
	   empty ones collapsed to 0px while the filled ones stayed narrow. */
	grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
	gap: 2rem 2.5rem;
	padding: 2.25rem 0 2.5rem;
	align-items: start;
}

/* A hairline under each heading gives the columns a shared baseline to sit on. */
.pgpl-hd__col-title {
	display: block;
	padding-bottom: 0.7rem;
	margin-bottom: 0.7rem;
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.45);
	text-decoration: none;
	border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

a.pgpl-hd__col-title:hover,
a.pgpl-hd__col-title:focus {
	color: #fff;
}

.pgpl-hd__col-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.pgpl-hd__col-list li {
	margin: 0 0 0.15rem;
}

.pgpl-hd__col-list a {
	display: flex;
	gap: 0.6rem;
	align-items: center;
	padding: 0.4rem 0.6rem;
	margin-left: -0.6rem;
	font-size: 0.9rem;
	font-weight: 500;
	color: rgba(255, 255, 255, 0.78);
	text-decoration: none;
	border-radius: 8px;
	/* transform is animated, not margin — margin would reflow the column. */
	transition: color 0.14s ease, background-color 0.14s ease, transform 0.14s ease;
}

.pgpl-hd__col-list a:hover,
.pgpl-hd__col-list a:focus {
	color: #fff;
	background: rgba(255, 255, 255, 0.08);
	transform: translateX(3px);
}

/*
 * The icon tile.
 *
 * Every link gets one, and every tile is the same size whether it holds an SVG
 * or a single letter — that shared footprint is what makes the column read as a
 * list rather than as ragged text. The monogram is a feature, not a fallback:
 * eleven CMS names have no meaningful shared icon, and repeating one generic
 * glyph eleven times reads as a bug.
 */
.pgpl-hd__ico {
	display: grid;
	flex: 0 0 1.6rem;
	place-items: center;
	width: 1.6rem;
	height: 1.6rem;
	font-size: 0.7rem;
	font-weight: 700;
	line-height: 1;
	color: rgba(255, 255, 255, 0.55);
	background: rgba(255, 255, 255, 0.07);
	border: 1px solid rgba(255, 255, 255, 0.09);
	border-radius: 7px;
	transition: color 0.14s ease, background-color 0.14s ease, border-color 0.14s ease;
}

.pgpl-hd__ico svg {
	width: 14px;
	height: 14px;
}

.pgpl-hd__col-list a:hover .pgpl-hd__ico,
.pgpl-hd__col-list a:focus .pgpl-hd__ico {
	color: #fff;
	background: var(--pgpl-ultra);
	border-color: var(--pgpl-ultra);
}

/* --- Membership card ------------------------------------------------------ */

/*
 * The only thing in the panel that is selling rather than navigating, so it is
 * the only thing given colour, depth and a border.
 *
 * Depth comes from four stacked layers, not one gradient: a deep navy base, a
 * diagonal ultramarine wash, a soft radial highlight top-right, and a 1px
 * inset white line that reads as a lit edge. A single two-stop gradient is what
 * makes a card look like a coloured rectangle instead of an object.
 */
.pgpl-hd__promo {
	position: relative;
	overflow: hidden;
	/* Grid items stretch to the row height by default, so a long category list
	   dragged this card to 451px of mostly empty gradient. */
	align-self: start;
	padding: 1.35rem 1.4rem 1.4rem;
	color: #fff;
	background:
		radial-gradient(120% 90% at 85% 0%, rgba(120, 150, 255, 0.55) 0%, rgba(120, 150, 255, 0) 60%),
		linear-gradient(155deg, #2436e4 0%, #1b29b8 55%, #131c86 100%);
	border-radius: 16px;
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, 0.22),
		0 18px 30px -18px rgba(19, 28, 134, 0.75);
}

/*
 * A large, very soft orb bleeding off the bottom-left corner. Blur plus low
 * opacity keeps it as texture rather than a shape you notice.
 */
.pgpl-hd__promo::after {
	content: "";
	position: absolute;
	bottom: -55%;
	left: -25%;
	width: 80%;
	aspect-ratio: 1;
	background: radial-gradient(circle, rgba(255, 255, 255, 0.16) 0%, rgba(255, 255, 255, 0) 70%);
	pointer-events: none;
}

.pgpl-hd__promo > * {
	position: relative;
	z-index: 1;
}

.pgpl-hd__promo-eyebrow {
	display: inline-flex;
	align-items: center;
	padding: 0.2rem 0.55rem;
	font-size: 0.6rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: #fff;
	background: rgba(255, 255, 255, 0.16);
	border: 1px solid rgba(255, 255, 255, 0.2);
	border-radius: 999px;
}

.pgpl-hd__promo-title {
	margin: 0.75rem 0 0;
	font-size: 1.15rem;
	font-weight: 800;
	line-height: 1.22;
	/* Tightened tracking is most of what separates a display line from body copy. */
	letter-spacing: -0.02em;
	color: #fff;
	text-wrap: balance;
}

.pgpl-hd__promo-body {
	margin: 0.4rem 0 1.1rem;
	font-size: 0.8rem;
	line-height: 1.55;
	color: rgba(255, 255, 255, 0.78);
}

.pgpl-hd__promo-btn,
.pgpl-hd__promo-btn:link,
.pgpl-hd__promo-btn:visited {
	display: inline-flex;
	gap: 0.4rem;
	align-items: center;
	padding: 0.55rem 1.1rem;
	font-size: 0.82rem;
	font-weight: 700;
	color: var(--pgpl-ultra-deep);
	text-decoration: none;
	background: #fff;
	border-radius: 9px;
	box-shadow: 0 6px 14px -8px rgba(0, 0, 0, 0.5);
	transition: transform 0.15s ease, box-shadow 0.15s ease;
}

/*
 * The one LIGHT surface in the chrome that holds a link, so it has to opt out of
 * the white-on-hover guard above — white text on a white button is invisible.
 *
 * The extra `.pgpl-hd` is doing real work: at (0,2,0) this rule loses to the
 * guard's (0,2,1), because an element selector still breaks the tie. Two classes
 * plus the pseudo puts it at (0,3,0) and back in control of its own colour.
 */
.pgpl-hd .pgpl-hd__promo-btn:hover,
.pgpl-hd .pgpl-hd__promo-btn:focus {
	color: var(--pgpl-ultra-deep);
	transform: translateY(-1px);
	box-shadow: 0 10px 18px -8px rgba(0, 0, 0, 0.55);
}

.pgpl-hd__promo-btn:focus-visible {
	outline: 2px solid #fff;
	outline-offset: 2px;
}

/*
 * The desktop navigation band that used to live here is gone.
 *
 * .pgpl-hd__nav, .pgpl-hd__menu-list and their .sub-menu dropdowns — 79 lines
 * — styled markup header.php stopped emitting when the nav bar folded into the
 * Browse panel. Nothing in header.php, footer.php, chrome.php or chrome.js has
 * referenced any of those classes since, so every rule was dead, and two live
 * rules elsewhere in this file were still naming .sub-menu in their selector
 * lists and quietly doing nothing.
 */
/* ---------------------------------------------------------------------------
 * Mobile drawer
 * ------------------------------------------------------------------------ */

.pgpl-drawer[hidden] {
	display: none;
}

.pgpl-drawer {
	position: fixed;
	inset: 0;
	z-index: 999;
}

.pgpl-drawer__scrim {
	position: absolute;
	inset: 0;
	background: rgba(4, 6, 14, 0.6);
	/* Blur the page behind so the panel reads as a layer, not a patch.
	   Safari needed the prefix until 18, which is most of the iPhones this
	   drawer exists for — unprefixed, they got a flat grey wash. */
	-webkit-backdrop-filter: blur(3px);
	backdrop-filter: blur(3px);
	opacity: 0;
	transition: opacity 0.24s ease;
}

.pgpl-drawer__panel {
	position: absolute;
	inset-block: 0;
	right: 0;
	display: flex;
	flex-direction: column;
	/*
	 * Wider than the old fixed 320px: category names like "Best WordPress
	 * Plugins" wrapped to two lines at 320, and a wrapped nav row reads as
	 * broken. Capped so it never becomes a full-screen takeover on a tablet.
	 */
	width: min(92vw, 400px);
	max-width: 100%;
	background: var(--pgpl-aurora-panel);
	border-left: 1px solid rgba(255, 255, 255, 0.08);
	box-shadow: -24px 0 60px rgba(0, 0, 0, 0.45);
	transform: translateX(100%);
	transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1);
}

.pgpl-drawer.is-open .pgpl-drawer__scrim {
	opacity: 1;
}

.pgpl-drawer.is-open .pgpl-drawer__panel {
	transform: translateX(0);
}

/* --- Pinned head ---------------------------------------------------------- */

.pgpl-drawer__head {
	display: flex;
	flex: 0 0 auto;
	gap: 0.6rem;
	align-items: center;
	/* env() keeps the head clear of a notch in landscape. */
	padding: 1rem calc(1.15rem + env(safe-area-inset-right)) 1rem 1.15rem;
	border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.pgpl-drawer__close {
	display: inline-flex;
	flex: 0 0 auto;
	/* 44px — the smallest target Apple and WCAG both consider reliable. */
	width: 44px;
	height: 44px;
	align-items: center;
	justify-content: center;
	color: rgba(255, 255, 255, 0.75);
	background: rgba(255, 255, 255, 0.06);
	border: 1px solid rgba(255, 255, 255, 0.1);
	/* The same icon-button component as the bar, so it takes the same shape. */
	border-radius: 999px;
	cursor: pointer;
	transition: color 0.15s ease, background-color 0.15s ease;
}

.pgpl-drawer .pgpl-drawer__close:hover,
.pgpl-drawer .pgpl-drawer__close:focus {
	color: #fff;
	background: rgba(255, 255, 255, 0.12);
}

/* --- Scrolling middle ----------------------------------------------------- */

.pgpl-drawer__scroll {
	flex: 1 1 auto;
	padding: 0.9rem 1.15rem 1.4rem;
	overflow-y: auto;
	/* Stop a flick at the end of the list from scrolling the page underneath. */
	overscroll-behavior: contain;
	-webkit-overflow-scrolling: touch;
}

/* The changelog chip, restated for the drawer's narrower measure. */
.pgpl-drawer__updates {
	display: flex;
	gap: 0.55rem;
	align-items: center;
	min-height: 44px;
	margin-bottom: 1rem;
	padding: 0.6rem 0.85rem;
	color: rgba(255, 255, 255, 0.9);
	font-size: 0.85rem;
	text-decoration: none;
	background: rgba(255, 255, 255, 0.05);
	border: 1px solid rgba(255, 255, 255, 0.09);
	border-radius: 14px;
}

.pgpl-drawer__updates-label {
	font-weight: 600;
}

.pgpl-drawer__updates-when {
	margin-left: auto;
	color: rgba(255, 255, 255, 0.5);
}

/* --- Rows ----------------------------------------------------------------- */

.pgpl-drawer__list,
.pgpl-drawer__sublist {
	margin: 0;
	padding: 0;
	list-style: none;
}

.pgpl-drawer__item + .pgpl-drawer__item {
	margin-top: 2px;
}

/*
 * One shared row shape for both the <a> destinations and the <button>
 * disclosures. They must be visually identical — the difference between them is
 * what they DO, and encoding that difference in the styling too would just make
 * the list look inconsistent.
 */
.pgpl-drawer__row {
	display: flex;
	width: 100%;
	gap: 0.75rem;
	align-items: center;
	padding: 0.6rem 0.7rem;
	color: rgba(255, 255, 255, 0.92);
	/* Buttons do not inherit the page font, and half these rows ARE buttons — so
	   without this the disclosures rendered in the system UI font directly beside
	   link rows in the theme's, which is exactly the inconsistency the comment
	   above forbids. .pgpl-hd__browse needs the same line for the same reason. */
	font-family: inherit;
	font-size: 0.95rem;
	font-weight: 600;
	line-height: 1.25;
	text-align: left;
	text-decoration: none;
	background: none;
	border: 0;
	border-radius: 14px;
	cursor: pointer;
	transition: background-color 0.15s ease, color 0.15s ease;
}

/*
 * "You are here" must not be reachable by accident.
 *
 * :hover and .is-current resolved to the identical declaration, and this rule
 * was not gated on pointer type — in a drawer that only ever opens on touch. A
 * tap latched :hover on whatever row was pressed and left it painted exactly
 * like the current page until something else was tapped, so the list could show
 * two "current" rows, neither of them right. The header's actions were already
 * gated for this; the drawer was not.
 *
 * Beats GeneratePress's `a:hover { color: var(--contrast) }` at (0,1,1).
 */
.pgpl-drawer .pgpl-drawer__row.is-current {
	color: #fff;
	background: rgba(255, 255, 255, 0.07);
}

.pgpl-drawer .pgpl-drawer__row:focus {
	color: #fff;
	background: rgba(255, 255, 255, 0.07);
}

@media (hover: hover) and (pointer: fine) {
	.pgpl-drawer .pgpl-drawer__row:hover {
		color: #fff;
		background: rgba(255, 255, 255, 0.07);
	}
}

/* Touch feedback that ends when the finger lifts, replacing the latched hover. */
.pgpl-drawer .pgpl-drawer__row:active {
	color: #fff;
	background: rgba(255, 255, 255, 0.13);
}

.pgpl-drawer__row-text {
	flex: 1 1 auto;
	min-width: 0;
}

/*
 * The glyph badge. Fixed 34px whether it holds an icon or a letter, so every
 * label in the list starts on the same vertical line.
 */
.pgpl-drawer__glyph {
	display: inline-flex;
	flex: 0 0 34px;
	width: 34px;
	height: 34px;
	align-items: center;
	justify-content: center;
	color: rgba(255, 255, 255, 0.8);
	font-size: 0.8rem;
	font-weight: 700;
	background: rgba(255, 255, 255, 0.06);
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: 11px;
}

.pgpl-drawer__glyph svg {
	width: 17px;
	height: 17px;
}

.pgpl-drawer__row:hover .pgpl-drawer__glyph,
.pgpl-drawer__row.is-current .pgpl-drawer__glyph {
	color: #fff;
	background: rgba(108, 134, 255, 0.22);
	border-color: rgba(108, 134, 255, 0.4);
}

/*
 * How many things are behind this row. It sets expectations before the tap —
 * "Other CMS · 12" is a different decision from "Other CMS · 2".
 */
.pgpl-drawer__count {
	flex: 0 0 auto;
	padding: 0.1rem 0.42rem;
	color: rgba(255, 255, 255, 0.55);
	font-size: 0.7rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	background: rgba(255, 255, 255, 0.07);
	border-radius: 999px;
}

.pgpl-drawer__caret,
.pgpl-drawer__go {
	display: inline-flex;
	flex: 0 0 auto;
	color: rgba(255, 255, 255, 0.45);
	transition: transform 0.22s ease, color 0.15s ease;
}

.pgpl-drawer__caret svg,
.pgpl-drawer__go svg {
	width: 15px;
	height: 15px;
}

.pgpl-drawer__row--toggle.is-open .pgpl-drawer__caret {
	color: #fff;
	transform: rotate(180deg);
}

.pgpl-drawer__row:hover .pgpl-drawer__go {
	color: #fff;
	transform: translateX(2px);
}

/* --- Expanded section ----------------------------------------------------- */

.pgpl-drawer__sub[hidden] {
	display: none;
}

.pgpl-drawer__sub {
	overflow: hidden;
}

.pgpl-drawer__sublist {
	/*
	 * A hairline rail tying the children to their parent. Cheaper and steadier
	 * than indenting alone, which at this width would crush the labels.
	 */
	margin: 0.15rem 0 0.4rem 1.25rem;
	padding-left: 0.85rem;
	border-left: 1px solid rgba(255, 255, 255, 0.1);
}

/*
 * min-height 44, like the close button and the foot CTAs.
 *
 * These rows sized themselves from their content — 42px with a glyph, 35px on
 * the glyphless "All …" row — in the one part of the site that is touch-only.
 * The drawer already held 44px as the standard in three places; the sublists
 * were simply never measured against it.
 */
.pgpl-drawer__sublink,
.pgpl-drawer__sub-all {
	display: flex;
	gap: 0.6rem;
	align-items: center;
	min-height: 44px;
	padding: 0.5rem 0.6rem;
	color: rgba(255, 255, 255, 0.62);
	font-size: 0.9rem;
	text-decoration: none;
	border-radius: 11px;
	transition: color 0.15s ease, background-color 0.15s ease;
}

.pgpl-drawer .pgpl-drawer__sublink:hover,
.pgpl-drawer .pgpl-drawer__sublink:focus,
.pgpl-drawer .pgpl-drawer__sub-all:hover,
.pgpl-drawer .pgpl-drawer__sub-all:focus,
.pgpl-drawer .pgpl-drawer__sublink.is-current {
	color: #fff;
	background: rgba(255, 255, 255, 0.06);
}

.pgpl-drawer .pgpl-drawer__sublink.is-current {
	font-weight: 600;
}

/* The child glyphs are quieter than their parent's — they are a level down. */
.pgpl-drawer__sublink .pgpl-drawer__glyph {
	flex-basis: 26px;
	width: 26px;
	height: 26px;
	font-size: 0.68rem;
	border-radius: 8px;
}

.pgpl-drawer__sublink .pgpl-drawer__glyph svg {
	width: 14px;
	height: 14px;
}

/* "All WordPress" — the parent link, which collapsing must not hide. */
.pgpl-drawer__sub-all {
	color: rgba(255, 255, 255, 0.5);
	font-size: 0.8rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-transform: uppercase;
}

/* --- Pinned foot ---------------------------------------------------------- */

.pgpl-drawer__foot {
	display: flex;
	flex: 0 0 auto;
	flex-direction: column;
	/* The inset keeps the buttons above the iPhone home indicator. */
	padding: 0.9rem 1.15rem calc(0.9rem + env(safe-area-inset-bottom));
	background: var(--pgpl-aurora-deep);
	border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.pgpl-drawer__btns {
	display: grid;
	gap: 0.6rem;
	grid-template-columns: 1fr 1fr;
}

.pgpl-drawer__btn {
	display: inline-flex;
	gap: 0.45rem;
	align-items: center;
	justify-content: center;
	min-height: 46px;
	padding: 0.6rem 0.8rem;
	color: #fff;
	font-size: 0.9rem;
	font-weight: 700;
	text-decoration: none;
	background: rgba(255, 255, 255, 0.07);
	border: 1px solid rgba(255, 255, 255, 0.12);
	border-radius: 14px;
	transition: background-color 0.15s ease;
}

.pgpl-drawer__btn svg {
	width: 17px;
	height: 17px;
}

.pgpl-drawer .pgpl-drawer__btn:hover,
.pgpl-drawer .pgpl-drawer__btn:focus {
	color: #fff;
	background: rgba(255, 255, 255, 0.13);
}

.pgpl-drawer .pgpl-drawer__btn--solid,
.pgpl-drawer .pgpl-drawer__btn--solid:link,
.pgpl-drawer .pgpl-drawer__btn--solid:visited,
.pgpl-drawer .pgpl-drawer__btn--solid:hover,
.pgpl-drawer .pgpl-drawer__btn--solid:focus {
	color: #fff;
	background: var(--pgpl-ultra);
	border-color: transparent;
}

/*
 * Pushed to the right of the head, so the brand keeps the left edge and the
 * currency sits with the close button as a pair of controls.
 */
.pgpl-drawer__currency {
	flex: 0 1 auto;
	margin-left: auto;
	min-width: 0;
}

/*
 * Slightly tighter horizontally than the desktop band's, to share a 294px head
 * at 320px — but tall enough to hit. At 0.22rem of vertical padding on 11.5px
 * text these were roughly 24px high with a 2px gap between them, the smallest
 * tap targets anywhere in the drawer and sitting in its pinned head where they
 * are permanently reachable.
 */
.pgpl-drawer__currency .pgpl-hd__chip {
	display: inline-flex;
	align-items: center;
	min-height: 40px;
	padding: 0 0.55rem;
}

/*
 * The active chip is a WHITE pill, so its label must stay dark. A blanket
 * `color:#fff` here painted white text on a white background and the selected
 * currency simply disappeared — the drawer showed a blank pill next to "INR".
 */
.pgpl-drawer__currency .pgpl-hd__chip.is-active {
	color: var(--pgpl-ink);
}

/*
 * A focus ring for keyboard users only. :focus-visible, not :focus — the drawer
 * moves focus on open, and a ring drawn around the logo after a thumb tap looks
 * like a rendering fault.
 *
 * White, because ultramarine on this panel measured 2.39:1 — under the 3:1 that
 * WCAG requires of a focus indicator, and this is the only one the drawer has:
 * the rule below removes the browser's. A keyboard user had no reliable way to
 * see where they were. The same #2436e4 is legible in the header only because
 * the header never draws it on a dark navy surface.
 */
.pgpl-drawer :focus-visible {
	outline: 2px solid #fff;
	outline-offset: 2px;
}

.pgpl-drawer :focus:not(:focus-visible) {
	outline: none;
}


/* ---------------------------------------------------------------------------
 * Footer
 * ------------------------------------------------------------------------ */

/*
 * The footer is built from the header's material, not its own.
 *
 * It used to be a flat slab of --pgpl-night while the header carried the Aurora
 * gradient and its glow, so the two ends of the page looked like they came from
 * different sites. Same base, same glow, same pills and cards — the page is now
 * bookended rather than merely terminated.
 */
.pgpl-ft {
	position: relative;
	overflow: hidden;
	color: rgba(255, 255, 255, 0.72);
	background: var(--pgpl-aurora-deep);
	font-size: 0.9rem;
}

/*
 * The glow, mirrored from the header. Weaker and higher than it was: it used to
 * light the membership band, and with that gone the same intensity would have
 * been a bright halo behind nothing in particular.
 */
.pgpl-ft::before {
	content: "";
	position: absolute;
	top: -55%;
	left: 50%;
	width: min(1100px, 120%);
	height: 420px;
	background: radial-gradient(ellipse at center, rgba(108, 134, 255, 0.11), transparent 70%);
	transform: translateX(-50%);
	pointer-events: none;
}

.pgpl-ft__wrap {
	position: relative;
	z-index: 1;
	max-width: 1240px;
	margin: 0 auto;
	padding: clamp(2.5rem, 5vw, 4rem) max(1rem, env(safe-area-inset-left)) 1.5rem;
}


.pgpl-ft a {
	color: rgba(255, 255, 255, 0.72);
	text-decoration: none;
	transition: color 0.15s ease;
}

.pgpl-ft a:hover,
.pgpl-ft a:focus {
	color: #fff;
}

/*
 * 1.2fr of a 1240px grid gave the brand block ~440px for 370px of content, so a
 * band of dead space ran down the middle of the footer while the three link
 * columns were squeezed against the right edge. 1fr / 1.6fr closes it.
 */
.pgpl-ft__top {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
	gap: clamp(2rem, 5vw, 4rem);
	padding-bottom: 2rem;
}

/* --- Brand ---------------------------------------------------------------- */

/* Grid child: without min-width:0 a long tagline word can widen the column. */
.pgpl-ft__brand {
	min-width: 0;
}

/* --- Wordmark (shared by header, drawer and footer) ----------------------- */

/*
 * "Pure" inherits its colour so the same markup reads correctly on the header's
 * white and the footer's navy. Only the GPL pill is pinned — it is the brand,
 * and it should not change with its surroundings.
 */
/*
 * The wordmark is the one thing here that must be in the DISPLAY face.
 *
 * chrome.php enqueues Bricolage Grotesque on every page — and this file did not
 * name a single font, so the brand mark inherited the body's Poppins and the
 * header rendered the shop's name in the wrong typeface everywhere it appears.
 * The stack matches single-download.css's `--display` exactly; declared
 * literally rather than as var(--display) because that token is defined per
 * template, and the chrome renders on pages that define none.
 *
 * Not applied to menu labels or actions: those are interface text and belong in
 * the body face, which is why the rest of this file inherits.
 */
.pgpl-mark {
	display: inline-flex;
	align-items: baseline;
	font-family: "Bricolage Grotesque", "Poppins", system-ui, sans-serif;
	font-weight: 800;
	letter-spacing: -0.02em;
	white-space: nowrap;
}

.pgpl-mark--sm { font-size: 1.1rem; }
.pgpl-mark--md { font-size: 1.35rem; }
.pgpl-mark--lg { font-size: 1.55rem; }

.pgpl-mark__pure {
	color: currentColor;
}

.pgpl-mark__gpl {
	margin-left: 0.22em;
	padding: 0 0.3em;
	color: #fff;
	background: var(--pgpl-ultra);
	border-radius: 0.25em;
}

/*
 * The header is dark, so the mark inherits white — and EVERY state is declared.
 *
 * GeneratePress ships `a:hover, a:focus, a:active { color: var(--contrast) }`,
 * which is #222. At (0,1,1) that outranks a single class, so a link here that
 * only declares its resting colour turns near-black the moment it is hovered —
 * invisible on this bar. Scoping with the parent lifts these to (0,2,0) and
 * settles it. The same trap caught the footer wordmark and the checkout button.
 */
.pgpl-hd .pgpl-hd__brand,
.pgpl-hd .pgpl-hd__brand:link,
.pgpl-hd .pgpl-hd__brand:visited,
.pgpl-hd .pgpl-hd__brand:hover,
.pgpl-hd .pgpl-hd__brand:focus,
.pgpl-hd .pgpl-hd__brand:active,
.pgpl-drawer .pgpl-drawer__brand,
.pgpl-drawer .pgpl-drawer__brand:link,
.pgpl-drawer .pgpl-drawer__brand:visited,
.pgpl-drawer .pgpl-drawer__brand:hover,
.pgpl-drawer .pgpl-drawer__brand:focus,
.pgpl-drawer .pgpl-drawer__brand:active {
	color: #fff;
	text-decoration: none;
}

.pgpl-hd .pgpl-hd__brand:hover .pgpl-mark__gpl,
.pgpl-hd .pgpl-hd__brand:focus .pgpl-mark__gpl {
	background: var(--pgpl-ultra-deep);
}

/*
 * Scoped with .pgpl-ft so it outranks the generic `.pgpl-ft a` rule, which is
 * (0,1,1) and was otherwise winning — rendering the wordmark at the footer's
 * 72%% link opacity instead of white.
 */
.pgpl-ft .pgpl-ft__word {
	display: inline-flex;
	color: #fff;
	text-decoration: none;
}

/*
 * 34ch capped the tagline at 308px inside a 440px column, so a band of empty
 * space sat between the brand block and the link columns and read as a layout
 * fault rather than as breathing room. 46ch still sits inside the comfortable
 * 45-75 character measure while using the column it was given.
 */
.pgpl-ft__tagline {
	max-width: 46ch;
	margin: 0.9rem 0 0;
	line-height: 1.6;
}

.pgpl-ft__social {
	display: flex;
	gap: 0.5rem;
	margin: 1.25rem 0 0;
	padding: 0;
	list-style: none;
}

.pgpl-ft__social a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.4rem;
	height: 2.4rem;
	background: rgba(255, 255, 255, 0.07);
	border: 1px solid rgba(255, 255, 255, 0.1);
	/* Circles, like every other icon-only control in the chrome. */
	border-radius: 999px;
	transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

@media (hover: hover) and (pointer: fine) {
	.pgpl-ft__social a:hover {
		color: #fff;
		background: var(--pgpl-ultra);
		border-color: transparent;
		transform: translateY(-2px);
	}
}

.pgpl-ft__social a:focus-visible {
	color: #fff;
	background: var(--pgpl-ultra);
}

.pgpl-ft__social a:active {
	transform: scale(0.94);
}

/* --- Columns -------------------------------------------------------------- */

.pgpl-ft__columns {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 1.5rem;
}

.pgpl-ft__column-title {
	display: flex;
	gap: 0.5rem;
	align-items: center;
	margin: 0 0 0.75rem;
	color: rgba(255, 255, 255, 0.45);
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	/* list-style + ::marker together remove the disclosure triangle everywhere. */
	list-style: none;
}

.pgpl-ft__column-title::-webkit-details-marker {
	display: none;
}

/* The chevron is only meaningful while these actually collapse. */
.pgpl-ft__column-title svg {
	display: none;
	width: 14px;
	height: 14px;
	margin-left: auto;
	transition: transform 0.2s ease;
}

.pgpl-ft__links {
	margin: 0;
	padding: 0;
	list-style: none;
}

.pgpl-ft__links li {
	margin: 0 0 0.5rem;
}

/*
 * A hover affordance the old flat list never had. The nudge is the same 2px
 * used by the drawer rows and the changelog chevron, so movement means the same
 * thing everywhere in the chrome.
 */
.pgpl-ft__links a {
	display: inline-block;
	transition: color 0.15s ease, transform 0.15s ease;
}

@media (hover: hover) and (pointer: fine) {
	.pgpl-ft__links a:hover {
		transform: translateX(2px);
	}
}

/* --- Legal ---------------------------------------------------------------- */

.pgpl-ft__legal {
	padding: 1rem 0;
	border-top: 1px solid rgba(255, 255, 255, 0.1);
	border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.pgpl-ft__legal-toggle {
	display: flex;
	gap: 0.5rem;
	align-items: center;
	font-size: 0.82rem;
	font-weight: 600;
	color: rgba(255, 255, 255, 0.6);
	cursor: pointer;
	list-style: none;
}

.pgpl-ft__legal-toggle::-webkit-details-marker {
	display: none;
}

.pgpl-ft__legal-toggle:hover {
	color: #fff;
}

.pgpl-ft__legal-toggle svg {
	transition: transform 0.2s ease;
}

.pgpl-ft__legal[open] .pgpl-ft__legal-toggle svg {
	transform: rotate(180deg);
}

.pgpl-ft__legal-toggle:focus-visible {
	outline: 2px solid #fff;
	outline-offset: 3px;
}

.pgpl-ft__legal-body {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
	gap: 1.5rem;
	margin-top: 1.25rem;
}

.pgpl-ft__legal-title {
	margin: 0 0 0.4rem;
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.5);
}

.pgpl-ft__legal-body p {
	margin: 0;
	font-size: 0.78rem;
	line-height: 1.65;
	color: rgba(255, 255, 255, 0.55);
}

.pgpl-ft__legal-body a {
	color: rgba(255, 255, 255, 0.8);
	text-decoration: underline;
}

/* --- Bottom --------------------------------------------------------------- */

.pgpl-ft__bottom {
	display: flex;
	flex-wrap: wrap;
	gap: 1rem;
	align-items: center;
	justify-content: space-between;
	padding-top: 1.25rem;
}

.pgpl-ft__copy {
	margin: 0;
	font-size: 0.8rem;
	color: rgba(255, 255, 255, 0.5);
}

.pgpl-ft__pay-group {
	display: flex;
	gap: 1rem;
	align-items: center;
	flex-wrap: wrap;
}

/*
 * Five card marks with nothing said about them are decoration. Naming what they
 * mean turns the same pixels into the reassurance a first-time buyer is looking
 * for at exactly the point they are deciding whether to trust the checkout.
 */
.pgpl-ft__secure {
	display: inline-flex;
	gap: 0.4rem;
	align-items: center;
	color: rgba(255, 255, 255, 0.6);
	font-size: 0.78rem;
	font-weight: 600;
}

.pgpl-ft__secure svg {
	width: 15px;
	height: 15px;
	color: #4ade80;
}

.pgpl-ft__pay {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.pgpl-ft__pay li {
	display: flex;
	margin: 0;
}

.pgpl-ft__pay svg {
	display: block;
	border-radius: 4px;
}

/* ---------------------------------------------------------------------------
 * Narrow screens
 * ------------------------------------------------------------------------ */

/*
 * ---------------------------------------------------------------------------
 * Phone and small tablet
 * ---------------------------------------------------------------------------
 *
 * The bar becomes TWO rows: brand and actions on the first, search across the
 * full width of the second.
 *
 * It has to. On a 390px screen the single row gave the search 108px of shell —
 * but Ajax Search Pro sizes its own inner box and stayed at 200px, so its submit
 * button was painted at x283-323 directly on top of the cart icon at x294-328.
 * Twenty-nine pixels of the cart were unreachable. Squeezing the row harder
 * would not have fixed that; the search needed its own line.
 *
 * It is also the right call independently. Search is how anyone actually finds
 * something in a 16,718-product catalogue — on a phone it deserves a full row,
 * not the scraps left over after four other controls.
 */
@media (max-width: 60rem) {
	.pgpl-hd__utility {
		display: none;
	}

	.pgpl-hd__browse,
	.pgpl-hd__panel {
		display: none;
	}

	/*
	 * The account dropdown is desktop-only, like Browse. On a phone the drawer
	 * already carries the whole account menu, and the control reverts to the
	 * direct link it has always been.
	 */
	.pgpl-hd__acct {
		display: none;
	}

	.pgpl-hd__action--compact {
		display: inline-flex;
	}

	.pgpl-hd__burger {
		display: inline-flex;
	}

	/*
	 * Hidden from the eye, kept for the accessibility tree.
	 *
	 * `display: none` here removed the only text node from Account and Cart, and
	 * their icons are aria-hidden — so on every phone and tablet both controls
	 * announced as an empty link. The cart's screen-reader sentence only exists
	 * when the cart is non-empty, so it covered nothing. Clipping instead keeps
	 * the label readable to assistive tech while it stays invisible on screen.
	 */
	.pgpl-hd__action-label {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		padding: 0;
		overflow: hidden;
		clip: rect(0 0 0 0);
		clip-path: inset(50%);
		white-space: nowrap;
		border: 0;
	}

	.pgpl-hd__command .pgpl-hd__wrap {
		flex-wrap: wrap;
		min-height: 0;
		gap: 0.6rem 0.75rem;
		padding-top: 0.75rem;
		padding-bottom: 0.75rem;
	}

	/*
	 * Explicit order, so the source stays in the desktop's logical reading order
	 * (brand → search → actions) while the phone shows brand → actions → search.
	 *
	 * This is a KNOWN, deliberate trade, kept after review — do not "fix" it by
	 * reordering the markup.
	 *
	 * One DOM order cannot match two different visual orders, and the two
	 * breakpoints genuinely want different ones. Whichever way the source is
	 * written, tab order disagrees with the eye at one breakpoint. Leaving the
	 * source as brand → search → actions puts the disagreement on mobile, where
	 * there is no Tab key and where a screen reader swipes the source order
	 * anyway — brand, search, actions, which reads perfectly well. Reordering the
	 * markup would move the disagreement onto desktop, which is where physical
	 * keyboards actually are, and would make Tab jump right to the account icons
	 * and then back left to the search field.
	 *
	 * The residual case is a sighted keyboard user on a window narrower than
	 * 960px. That is the smaller harm, and it is the one we chose.
	 */
	.pgpl-hd__brand {
		order: 1;
	}

	.pgpl-hd__actions {
		order: 2;
		margin-left: auto;
		gap: 0.15rem;
	}

	.pgpl-hd__search {
		order: 3;
		/* The whole second row. flex-basis 100% forces the wrap. */
		flex: 1 1 100%;
		width: 100%;
	}

	/*
	 * Ajax Search Pro sizes its wrappers itself and ignores the flex shell around
	 * them. Without this the plugin's 200px box overhangs a 108px container and
	 * lands on the cart icon. Scoped to our header and to phone widths only.
	 */
	/* Comfortable thumb targets; 16px stops iOS zooming the page on focus. */
	.pgpl-hd__search input[type="search"],
	.pgpl-hd__search input[type="text"],
	.pgpl-hd__search .orig,
	.pgpl-hd__search .autocomplete {
		font-size: 16px !important;
	}

	/*
	 * Icon-only, so the box must centre its glyph.
	 *
	 * .pgpl-hd__action is a flex row built for icon + label. With the label
	 * hidden it kept flex-start, so an 18px icon sat against the left edge of a
	 * 42px box and the highlight appeared to hang off to one side — the thing
	 * that read as "the hover is wrong". The burger already centred; the links
	 * never did.
	 */
	/*
	 * 44px, not 42. These are touch-only controls — the burger renders nowhere
	 * else — and this file already calls 44 "the smallest target Apple and WCAG
	 * both consider reliable" where the drawer's close button is sized. Missing
	 * it by two pixels on the three controls a phone visitor actually taps was
	 * the one place that standard was not applied.
	 */
	.pgpl-hd__action,
	.pgpl-hd__burger {
		width: 44px;
		height: 44px;
		padding: 0;
		justify-content: center;
	}

	/*
	 * Here — and only here — the badge comes out of the flow.
	 *
	 * With the label clipped, the action is a 44px square holding an 18px icon.
	 * In flow the badge was still a flex sibling: 18px icon + 6.4px gap + an
	 * 18.4px badge is over 42px of content before the count reaches two digits,
	 * so it burst the circle and crowded the burger next to it. Pinned to the
	 * corner it sits over the icon's own dead space, which is what the
	 * `position: relative` on .pgpl-hd__action was always there for.
	 *
	 * The ring is the bar's own colour, so the badge reads as a separate object
	 * rather than a blob fused to the icon.
	 */
	.pgpl-hd__action .pgpl-hd__badge {
		position: absolute;
		top: 1px;
		right: 1px;
		pointer-events: none;
		box-shadow: 0 0 0 2px var(--pgpl-aurora);
	}

	/* The wordmark simply gets smaller; no separate mobile asset needed. */
	.pgpl-hd__brand .pgpl-mark {
		font-size: 1.15rem;
	}

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

}

/*
 * Phone: the link columns collapse.
 *
 * Stacked open they ran the footer to 750px with an orphaned third column
 * sitting alone on its own row. Closed, the whole footer fits in roughly half
 * that, and the headings become a scannable index instead of three long lists
 * someone has to swipe past to reach the copyright.
 */
@media (max-width: 40rem) {
	.pgpl-ft__columns {
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
	}

	.pgpl-ft__column {
		border-top: 1px solid rgba(255, 255, 255, 0.08);
	}

	.pgpl-ft__column-title {
		margin: 0;
		padding: 0.95rem 0;
		font-size: 0.78rem;
		letter-spacing: 0.08em;
	}

	.pgpl-ft__column-title svg {
		display: block;
	}

	.pgpl-ft__column[open] .pgpl-ft__column-title svg {
		transform: rotate(180deg);
	}

	.pgpl-ft__links {
		padding-bottom: 0.85rem;
	}

	.pgpl-ft__links li {
		margin: 0 0 0.75rem;
	}

	.pgpl-ft__bottom {
		align-items: flex-start;
		flex-direction: column;
	}
}

/*
 * Everything that MOVES, not a sample of it.
 *
 * This list covered five selectors, one of which (.pgpl-hd__menu-list .sub-menu)
 * had no markup left to match, while the Browse panel's slide, the accordion
 * caret's 180° spin, every column-link and arrow nudge and the footer's social
 * lift all kept animating. Someone who has asked the operating system to stop
 * motion had most of the chrome ignore them.
 *
 * Transitions are removed rather than zeroed, and the transformed elements are
 * pinned at their resting position, so nothing lands mid-animation. The one
 * transform that must survive is the caret's open state — it is the only signal
 * that a section is expanded, so it snaps instead of sliding.
 */
@media (prefers-reduced-motion: reduce) {
	.pgpl-hd__action,
	.pgpl-hd__burger,
	.pgpl-drawer__panel,
	.pgpl-drawer__scrim,
	.pgpl-hd__panel,
	.pgpl-hd__acct-menu,
	.pgpl-hd__acct-toggle svg:last-child,
	.pgpl-hd__acct-nav a,
	.pgpl-hd__acct-out,
	.pgpl-hd__updates-arrow,
	.pgpl-hd__col-list a,
	.pgpl-hd__promo-btn,
	.pgpl-hd__browse svg,
	.pgpl-drawer__caret,
	.pgpl-drawer__go,
	.pgpl-drawer__row,
	.pgpl-ft__social a,
	.pgpl-ft__links a,
	.pgpl-ft__legal-toggle svg {
		transition: none;
	}

	/* No press-scale, and no decorative travel, for anyone who has asked
	   motion to stop. */
	.pgpl-hd__action:active,
	.pgpl-hd__burger:active,
	.pgpl-hd__updates:hover .pgpl-hd__updates-arrow,
	.pgpl-hd__updates:focus .pgpl-hd__updates-arrow,
	.pgpl-hd__col-list a:hover,
	.pgpl-hd__col-list a:focus,
	.pgpl-hd__promo-btn:hover,
	.pgpl-hd__promo-btn:focus,
	.pgpl-drawer__row:hover .pgpl-drawer__go,
	.pgpl-ft__social a:hover,
	.pgpl-ft__social a:focus,
	.pgpl-ft__links a:hover,
	.pgpl-ft__links a:focus {
		transform: none;
	}
}
