/* =========================================================================
   PakTameer storefront
   One stylesheet, one request. Ordered: fonts, tokens, reset, base,
   layout, components.
   ========================================================================= */

/* ------------------------------------------------------------------ fonts */

@font-face {
	font-family: 'Archivo';
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url('../fonts/archivo-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
		U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
		U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
	font-family: 'Archivo';
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url('../fonts/archivo-latin-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
		U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
		U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ----------------------------------------------------------------- tokens */

:root {
	/*
	 * Warm neutrals. The page sits on a soft stone ground (#f6f6f3) so that
	 * cards, panels and product photography can be genuinely white and read as
	 * raised against it. Text is never pure black — that would be harsh against
	 * warm interior shots.
	 */
	/* Hex, not OKLCH: this is a specified brand value rather than a derived one,
	   and the nearest OKLCH rounds to #f5f5f2 — a point off. */
	--pt-paper: #f6f6f3;                    /* page ground */
	--pt-card: oklch(1 0 0);                /* cards, inputs, product frames */
	--pt-surface: oklch(0.9485 0.0045 100); /* panels that sit below the ground */
	--pt-surface-deep: oklch(0.918 0.006 96);
	--pt-line: oklch(0.888 0.006 96);
	--pt-line-strong: oklch(0.815 0.008 92);

	--pt-ink: oklch(0.205 0.013 60);
	--pt-ink-soft: oklch(0.39 0.012 62);
	--pt-muted: oklch(0.556 0.011 65);

	/* Brand bronze, cleaned up from the original #b87743. Accent only —
	   the photography carries the colour on this site. */
	--pt-bronze: oklch(0.632 0.106 58);
	--pt-bronze-deep: oklch(0.512 0.098 54);
	--pt-bronze-tint: oklch(0.955 0.022 70);

	--pt-sale: oklch(0.53 0.16 25);

	/* WhatsApp's brand green. Paired with ink rather than white text: white on
	   #25d366 measures about 2:1, which is unreadable, while ink clears 8:1 and
	   still reads unmistakably as WhatsApp. */
	--pt-whatsapp: #25d366;
	--pt-focus: oklch(0.55 0.15 250);

	/* Fluid type. Ratio holds above 1.25 between steps. */
	--pt-text-2xs: 0.6875rem;
	--pt-text-xs: 0.78125rem;
	--pt-text-sm: 0.875rem;
	--pt-text-base: 1rem;
	--pt-text-lg: 1.125rem;
	--pt-text-xl: clamp(1.25rem, 0.6vw + 1.1rem, 1.5rem);
	--pt-text-2xl: clamp(1.6rem, 1.2vw + 1.3rem, 2.125rem);
	--pt-text-3xl: clamp(2.1rem, 2.4vw + 1.5rem, 3.25rem);
	--pt-text-4xl: clamp(2.6rem, 4.4vw + 1.5rem, 4.75rem);

	--pt-tracking-tight: -0.022em;
	--pt-tracking-snug: -0.012em;
	--pt-tracking-wide: 0.08em;
	--pt-tracking-wider: 0.16em;

	/* Spacing. Deliberately uneven at the top end so rhythm varies. */
	--pt-space-1: 0.25rem;
	--pt-space-2: 0.5rem;
	--pt-space-3: 0.75rem;
	--pt-space-4: 1rem;
	--pt-space-5: 1.5rem;
	--pt-space-6: 2rem;
	--pt-space-7: 3rem;
	--pt-space-8: 4.5rem;
	--pt-space-9: 7rem;

	--pt-radius-sm: 4px;
	--pt-radius: 10px;
	--pt-radius-lg: 16px;
	--pt-radius-full: 999px;

	/* Height shared by the quantity stepper, add-to-cart and WhatsApp button,
	   so the buy area is one consistent control size. */
	--pt-control-h: 56px;

	/* Gap between the stacked buy controls. One token so the three gaps cannot
	   drift apart, which is how they ended up at 24px each. */
	--pt-buy-gap: 0.625rem;

	--pt-shell: 1400px;
	--pt-mega-width: 1080px;
	/* Panel ground. Deliberately not white: the header is white, so a white
	   panel merged into it with only a hairline between the two. */
	--pt-mega-bg: var(--pt-surface);
	--pt-gutter: clamp(1rem, 3.5vw, 3rem);

	/* Exponential ease-out. No bounce. */
	--pt-ease: cubic-bezier(0.22, 1, 0.36, 1);
	--pt-ease-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
	--pt-fast: 160ms;
	--pt-med: 320ms;
	--pt-slow: 620ms;
}

/* ------------------------------------------------------------------ reset */

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

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
}

body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd {
	margin: 0;
}

ul[class],
ol[class] {
	list-style: none;
	margin: 0;
	padding: 0;
}

img,
picture,
svg,
video {
	display: block;
	max-width: 100%;
}

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

button {
	cursor: pointer;
}

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

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

/* ------------------------------------------------------------------- base */

body {
	background: var(--pt-paper);
	color: var(--pt-ink);
	font-family: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
	font-size: var(--pt-text-base);
	font-weight: 400;
	line-height: 1.6;
	font-variant-numeric: tabular-nums;
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
	font-weight: 700;
	line-height: 1.08;
	letter-spacing: var(--pt-tracking-tight);
	text-wrap: balance;
}

h1 { font-size: var(--pt-text-4xl); }
h2 { font-size: var(--pt-text-3xl); }
h3 { font-size: var(--pt-text-2xl); }
h4 { font-size: var(--pt-text-xl); letter-spacing: var(--pt-tracking-snug); }

p {
	max-width: 68ch;
}

a {
	color: inherit;
	text-decoration-color: color-mix(in oklch, currentColor 35%, transparent);
	text-underline-offset: 0.18em;
	transition: color var(--pt-fast) var(--pt-ease);
}

a:hover {
	color: var(--pt-bronze-deep);
}

:focus-visible {
	outline: 2px solid var(--pt-focus);
	outline-offset: 3px;
	border-radius: var(--pt-radius-sm);
}

.pt-visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.pt-skip-link {
	position: absolute;
	top: -100%;
	left: var(--pt-space-4);
	z-index: 999;
	padding: var(--pt-space-3) var(--pt-space-5);
	background: var(--pt-ink);
	color: var(--pt-paper);
	border-radius: 0 0 var(--pt-radius) var(--pt-radius);
	text-decoration: none;
}

.pt-skip-link:focus {
	top: 0;
}

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

.pt-shell {
	width: min(100% - (var(--pt-gutter) * 2), var(--pt-shell));
	margin-inline: auto;
}

.pt-shell--wide {
	width: min(100% - (var(--pt-gutter) * 2), 1680px);
	margin-inline: auto;
}

/* Section headings: a small eyebrow, a large title, an optional link. */
.pt-section-head {
	display: flex;
	flex-wrap: wrap;
	align-items: end;
	justify-content: space-between;
	gap: var(--pt-space-4);
	margin-bottom: var(--pt-space-6);
}

.pt-eyebrow {
	font-size: var(--pt-text-2xs);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-wider);
	text-transform: uppercase;
	color: var(--pt-muted);
	margin-bottom: var(--pt-space-2);
}

/*
 * The section's "see the rest" action, as a filled pill.
 *
 * Same treatment as .pt-btn rather than a variant of its own, so the one button
 * shape on the site stays one button shape — these sit on the same page as the
 * product buttons and any second filled style would read as a different kind of
 * action rather than the same one in a different place.
 */
.pt-section-link {
	display: inline-flex;
	align-items: center;
	gap: var(--pt-space-2);
	padding: 0.8125rem 1.5rem;
	border: 1px solid transparent;
	border-radius: var(--pt-radius-full);
	background: var(--pt-ink);
	font-size: var(--pt-text-sm);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-snug);
	text-decoration: none;
	color: var(--pt-paper);
	white-space: nowrap;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		border-color var(--pt-fast) var(--pt-ease),
		color var(--pt-fast) var(--pt-ease);
}

/* Sized in ems so it tracks the label rather than sitting at a fixed weight. */
.pt-section-link::after {
	content: '\2197';
	font-size: 0.95em;
	line-height: 1;
}

.pt-section-link:hover,
.pt-section-link:focus-visible {
	background: var(--pt-bronze-deep);
	border-color: var(--pt-bronze-deep);
	color: var(--pt-paper);
}

/* -------------------------------------------------------------- hero slider */

/*
 * The artwork is the whole slide — the wording is already in the picture — so
 * there is no overlay layer here, only a frame and the controls.
 *
 * The two ratio tokens are written inline by the template from the first
 * slide's real dimensions, so the box is the right shape before a single byte
 * of the banner has arrived and nothing below it jumps on load.
 */
.pt-hero {
	position: relative;
	/* Edge to edge, and flush to the header — no radius, no gutters. */
	width: 100%;
	margin-top: 0;
	margin-bottom: var(--pt-space-7);
	overflow: hidden;
	background: var(--pt-surface);
}

.pt-hero__viewport {
	overflow: hidden;
	aspect-ratio: var(--pt-hero-ratio-desk, 16 / 6);
}

ul.pt-hero__track {
	display: flex;
	height: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
	transition: transform 600ms cubic-bezier(0.4, 0, 0.2, 1);
}

.pt-hero__slide {
	flex: 0 0 100%;
	min-width: 0;
	height: 100%;
	position: relative;
}

.pt-hero__link {
	display: block;
	height: 100%;
}

/*
 * cover, not contain: the viewport is cut to the first slide's proportions, so
 * matching artwork fills it exactly and nothing is trimmed. Slides uploaded at
 * a different shape lose their edges — which is why the editor asks for one
 * size throughout.
 */
.pt-hero__slide :is(img, video, .pt-hero__pic) {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

.pt-hero__slot[hidden] { display: none; }

/* Arrows */

.pt-hero__arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	border-radius: var(--pt-radius-full);
	background: rgb(255 255 255 / 0.82);
	color: var(--pt-ink);
	cursor: pointer;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		opacity var(--pt-fast) var(--pt-ease);
}

.pt-hero__arrow:hover { background: rgb(255 255 255 / 0.98); }

.pt-hero__arrow svg { width: 17px; height: 17px; }

.pt-hero__arrow--prev { left: var(--pt-space-4); }
.pt-hero__arrow--next { right: var(--pt-space-4); }

/* The shared arrow mark points right; the previous control is its mirror. */
.pt-hero__arrow--prev svg { transform: scaleX(-1); }

/* Controls */

.pt-hero__controls {
	position: absolute;
	left: 50%;
	bottom: var(--pt-space-4);
	transform: translateX(-50%);
	display: flex;
	align-items: center;
	gap: var(--pt-space-3);
	padding: 0.4rem 0.7rem;
	border-radius: var(--pt-radius-full);
	background: rgb(255 255 255 / 0.82);
}

.pt-hero__dots {
	display: flex;
	align-items: center;
	gap: 0.45rem;
}

.pt-hero__dot {
	width: 7px;
	height: 7px;
	padding: 0;
	border: 0;
	border-radius: var(--pt-radius-full);
	background: var(--pt-line-strong);
	cursor: pointer;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		width var(--pt-fast) var(--pt-ease);
}

/* The current slide's dot stretches rather than just recolouring, so the
   position is readable without relying on colour alone. */
.pt-hero__dot[aria-selected='true'] {
	width: 22px;
	background: var(--pt-ink);
}

.pt-hero__playpause {
	display: grid;
	place-items: center;
	width: 20px;
	height: 20px;
	padding: 0;
	border: 0;
	background: none;
	color: var(--pt-ink);
	cursor: pointer;
}

.pt-hero__playpause .pt-hero__icon-play { display: none; }
.pt-hero.is-paused .pt-hero__playpause .pt-hero__icon-play { display: block; }
.pt-hero.is-paused .pt-hero__playpause .pt-hero__icon-pause { display: none; }

@media (max-width: 767.98px) {
	.pt-hero__viewport { aspect-ratio: var(--pt-hero-ratio-mob, 4 / 5); }

	/* Arrows would sit over the artwork on a phone; the dots and a swipe are
	   enough, and both leave the banner unobstructed. */
	.pt-hero__arrow { display: none; }

	.pt-hero__controls { bottom: var(--pt-space-3); }
}

@media (prefers-reduced-motion: reduce) {
	ul.pt-hero__track { transition: none; }
}

/* -------------------------------------------------------------- promo breaks */

/*
 * Promotional bands between the product sections.
 *
 * Held inside the page shell like every other section, and given the same
 * corner radius as the bento tiles and product cards, so they read as part of
 * the page rather than something pasted across it. The hero is the only band
 * that runs edge to edge.
 */
.pt-break {
	display: block;
	border-radius: var(--pt-radius-lg);
	background: var(--pt-surface);
	overflow: hidden;
}

/*
 * No `width: 100%` above, deliberately. A block-level band already fills its
 * container, and declaring the width here ties with the shell class the caller
 * puts on a standalone band — which then loses on source order and the band
 * spills the full width of the window.
 *
 * A band inside a pair is spaced by the wrapper; a standalone one is the one
 * carrying a shell class, so that is what the spacing hangs off.
 */
.pt-break.pt-shell--wide {
	margin-block: var(--pt-space-8);
}

.pt-break__media {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

/*
 * Shown at the artwork's own proportions, not cropped.
 *
 * At half the shell a band is around 650px wide and 370px tall, which is a
 * comfortable size — the crop only became necessary when these ran the full
 * width of the window and stood over 800px tall.
 */
.pt-break--wide { aspect-ratio: 7 / 4; }

/*
 * The strip is drawn at 5.6:1. On a phone that is barely 60px tall and the
 * wording set into it falls below reading size, so it is cropped to its middle
 * — which is where the message and the button sit.
 */
.pt-break--ribbon { aspect-ratio: 3 / 1; }

@media (min-width: 700px) {
	.pt-break--ribbon { aspect-ratio: 2560 / 458; }
}

/* Side by side above the tablet breakpoint, stacked below it. */
.pt-breaks {
	display: grid;
	gap: clamp(0.75rem, 1.5vw, 1.5rem);
	grid-template-columns: 1fr;
	margin-block: var(--pt-space-8);
}

@media (min-width: 700px) {
	.pt-breaks { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* A link band should say so on hover, without a filter that would tint the
   artwork the client signed off. */
a.pt-break .pt-break__media {
	transform: scale(1.01);
	transition: transform var(--pt-slow) var(--pt-ease-quart);
}

a.pt-break:hover .pt-break__media,
a.pt-break:focus-visible .pt-break__media {
	transform: scale(1.035);
}

/* -------------------------------------------------------------- category bento */

/*
 * Asymmetric grid: the largest category gets a double-height feature tile,
 * the rest fill around it. Deliberately not an identical card grid — the
 * tile size signals catalogue depth.
 */
.pt-bento {
	display: grid;
	gap: clamp(0.5rem, 1vw, 0.875rem);
	grid-template-columns: repeat(2, 1fr);
}

/*
 * Two columns: the feature takes a full-width band of its own, which leaves an
 * even number of cells for the rest. Left as a single column it pairs off with
 * a neighbour and strands the last tile beside a hole.
 */
.pt-bento__tile--feature,
.pt-bento__cta {
	grid-column: 1 / -1;
}

@media (min-width: 700px) {
	.pt-bento {
		grid-template-columns: repeat(4, 1fr);
		grid-auto-rows: minmax(0, 1fr);
	}

	.pt-bento__tile--feature {
		grid-column: span 2;
		grid-row: span 2;
	}

	/* Whatever the categories left over — see the template for the sum. */
	.pt-bento__cta {
		grid-column: span var(--pt-cta-span, 2);
	}
}

.pt-bento__tile {
	position: relative;
	display: block;
	overflow: hidden;
	border-radius: var(--pt-radius-lg);
	background: var(--pt-surface-deep);
	aspect-ratio: 3 / 2;
	text-decoration: none;
	isolation: isolate;
}

.pt-bento__tile--feature {
	aspect-ratio: 3 / 2;
}

@media (min-width: 700px) {
	.pt-bento__tile--feature {
		aspect-ratio: auto;
	}
}

.pt-bento__media {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	/* cover is correct here: these are atmospheric room scenes, not products.
	   Cropping a room edge costs nothing. Products always use contain. */
	object-fit: cover;
	transform: scale(1.01);
	transition: transform var(--pt-slow) var(--pt-ease-quart);
}

.pt-bento__tile:hover .pt-bento__media,
.pt-bento__tile:focus-visible .pt-bento__media {
	transform: scale(1.055);
}

/* Scrim only where the text sits, so the photography stays bright. */
.pt-bento__tile::after {
	content: '';
	position: absolute;
	inset: 35% 0 0;
	background: linear-gradient(
		to bottom,
		oklch(0.20 0.013 60 / 0) 0%,
		oklch(0.20 0.013 60 / 0.42) 55%,
		oklch(0.18 0.013 60 / 0.76) 100%
	);
	pointer-events: none;
	z-index: 1;
}

.pt-bento__body {
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	z-index: 2;
	display: flex;
	align-items: end;
	justify-content: space-between;
	gap: var(--pt-space-4);
	padding: clamp(0.875rem, 2vw, 1.75rem);
	color: oklch(0.99 0 0);
}

.pt-bento__name {
	font-size: clamp(1.05rem, 1.6vw, 1.75rem);
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: var(--pt-tracking-tight);
	margin-bottom: var(--pt-space-1);
}

.pt-bento__tile--feature .pt-bento__name {
	font-size: clamp(1.4rem, 2.6vw, 2.6rem);
}

.pt-bento__count {
	font-size: var(--pt-text-2xs);
	font-weight: 500;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	opacity: 0.82;
}

.pt-bento__go {
	flex: none;
	display: grid;
	place-items: center;
	width: clamp(2rem, 3.2vw, 2.75rem);
	aspect-ratio: 1;
	border: 1px solid oklch(0.99 0 0 / 0.5);
	border-radius: var(--pt-radius-full);
	transition:
		background-color var(--pt-med) var(--pt-ease),
		border-color var(--pt-med) var(--pt-ease),
		color var(--pt-med) var(--pt-ease);
}

.pt-bento__go svg {
	width: 42%;
	height: auto;
}

.pt-bento__tile:hover .pt-bento__go,
.pt-bento__tile:focus-visible .pt-bento__go {
	background: oklch(0.99 0 0);
	border-color: oklch(0.99 0 0);
	color: var(--pt-ink);
}

/*
 * Closing tile.
 *
 * Deliberately not another photograph: a run of room scenes ending in one more
 * room scene reads as a category the visitor has to evaluate. Flat ink makes it
 * plainly a way out of the grid rather than another thing in it, and gives the
 * bottom row a deliberate edge instead of a gap.
 */
.pt-bento__cta {
	background: var(--pt-ink);
	color: oklch(0.99 0 0);
	aspect-ratio: auto;
	min-height: 8.5rem;
}

/* Flat by default: with no image there is nothing to darken. */
.pt-bento__cta::after { content: none; }

/*
 * With an image, the scrim covers the whole tile rather than fading in from 35%
 * like the category tiles. Those are selling the photograph; this one is
 * selling the sentence on top of it, and it carries three lines including a
 * bronze eyebrow that needs a dark, even ground to stay legible. The picture
 * survives as texture and depth, not as the subject.
 */
.pt-bento__cta--image::after {
	content: '';
	inset: 0;
	background: linear-gradient(
		to bottom,
		oklch(0.205 0.013 60 / 0.70) 0%,
		oklch(0.205 0.013 60 / 0.83) 60%,
		oklch(0.18 0.013 60 / 0.93) 100%
	);
	opacity: 1;
	transition: opacity var(--pt-med) var(--pt-ease);
}

/*
 * On hover the scrim lifts and the photograph comes forward.
 *
 * The tile inherits the grid's shared image zoom, but under a scrim this heavy
 * the zoom is invisible as movement and only shows as the picture shifting
 * under a near-solid panel — which reads as a rendering fault rather than a
 * response. Lifting the scrim gives that same zoom something to reveal, so the
 * two effects become one gesture.
 *
 * Opacity rather than a second gradient: gradient interpolation is not
 * dependable across engines, and a compositor-only property keeps the whole
 * tile — image, scrim and arrow — moving together.
 *
 * 0.78 is the floor. Below that the bronze eyebrow starts to compete with
 * whatever is in the photograph behind it, and the tile stops being readable
 * at a glance.
 */
.pt-bento__cta--image:hover::after,
.pt-bento__cta--image:focus-visible::after {
	opacity: 0.78;
}

.pt-bento__cta-inner {
	position: absolute;
	inset: 0;
	/* Above the scrim, matching .pt-bento__body on the category tiles. */
	z-index: 2;
	display: flex;
	align-items: end;
	justify-content: space-between;
	gap: var(--pt-space-4);
	padding: clamp(0.875rem, 2vw, 1.75rem);
}

.pt-bento__cta-eyebrow {
	display: block;
	font-size: var(--pt-text-2xs);
	font-weight: 500;
	letter-spacing: var(--pt-tracking-wider);
	text-transform: uppercase;
	color: var(--pt-bronze);
	margin-bottom: var(--pt-space-2);
}

.pt-bento__cta-title {
	display: block;
	font-size: clamp(1.05rem, 1.6vw, 1.75rem);
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: var(--pt-tracking-tight);
	margin-bottom: var(--pt-space-1);
}

.pt-bento__cta-meta {
	display: block;
	font-size: var(--pt-text-2xs);
	font-weight: 500;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	opacity: 0.72;
}

.pt-bento__cta .pt-bento__go {
	border-color: oklch(0.99 0 0 / 0.4);
}

.pt-bento__cta:hover .pt-bento__go,
.pt-bento__cta:focus-visible .pt-bento__go {
	background: var(--pt-bronze);
	border-color: var(--pt-bronze);
	color: var(--pt-ink);
}

/* ------------------------------------------------------- product image frame */

/*
 * The square rule. `contain` never crops — a wide sofa gets white bands above
 * and below, a tall wardrobe gets them left and right. The imported files are
 * already padded to square; this guarantees it for anything uploaded later or
 * served at a different aspect.
 */
.pt-frame {
	position: relative;
	aspect-ratio: 1;
	overflow: hidden;
	border-radius: var(--pt-radius);
	background: var(--pt-card);
}

.pt-frame img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	transition: transform var(--pt-slow) var(--pt-ease-quart);
}

.pt-frame--hoverable:hover img {
	transform: scale(1.04);
}

/* Secondary image revealed on hover, matching the old site's behaviour. */
.pt-frame__alt {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity var(--pt-med) var(--pt-ease);
}

.pt-frame--hoverable:hover .pt-frame__alt {
	opacity: 1;
}

/* ---------------------------------------------------------- product grid */

.pt-products {
	display: grid;
	gap: clamp(1rem, 2vw, 2rem) clamp(0.75rem, 1.5vw, 1.5rem);
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 640px) {
	.pt-products { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 1100px) {
	.pt-products { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/*
 * A band meant to be exactly one row.
 *
 * Four products is a row at four columns and two clean pairs at two, but at the
 * three-column width it becomes a row of three with a single card stranded
 * beneath it. Dropping the fourth there keeps the band one row wherever it is
 * one row, rather than sometimes being a row and a remainder.
 *
 * The card is hidden rather than not queried: the breakpoint is a rendering
 * concern, and asking the server for a different number of products per screen
 * width is not something a cached page can answer.
 */
@media (min-width: 640px) and (max-width: 1099.98px) {
	/*
	 * Qualified with .pt-card on purpose. `.pt-products--row > :nth-child(4)`
	 * carries the same weight as the `.pt-products > .pt-card` display rule
	 * further down the file, which then wins on order and the card stays
	 * visible — a media query adds no specificity to break the tie.
	 */
	.pt-products--row > .pt-card:nth-child(4) { display: none; }
}

/*
 * Product card.
 *
 * White on the stone ground, with a hairline border rather than a drop shadow —
 * shadows on a warm background go muddy, and 24 of them on a page reads as
 * noise. The border does the separating; the hover state does the rest.
 */
.pt-card {
	display: flex;
	flex-direction: column;
	height: 100%;
	background: var(--pt-card);
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-lg);
	overflow: hidden;
	transition:
		border-color var(--pt-med) var(--pt-ease),
		box-shadow var(--pt-med) var(--pt-ease),
		transform var(--pt-med) var(--pt-ease);
}

.pt-card:hover {
	border-color: var(--pt-line-strong);
	box-shadow: 0 10px 28px -18px oklch(0.28 0.02 70 / 0.45);
	transform: translateY(-2px);
}

.pt-card__link {
	text-decoration: none;
	color: inherit;
	display: contents;
}

/* The frame is clipped by the card, so it drops its own rounding. */
.pt-card .pt-frame {
	border-radius: 0;
	background: var(--pt-card);
}

.pt-card__meta {
	display: flex;
	flex-direction: column;
	gap: var(--pt-space-2);
	padding: var(--pt-space-4) var(--pt-space-4) var(--pt-space-5);
	border-top: 1px solid var(--pt-line);
	margin-top: auto;
}

.pt-card__name {
	font-size: var(--pt-text-sm);
	font-weight: 500;
	line-height: 1.35;
	letter-spacing: var(--pt-tracking-snug);
	color: var(--pt-ink-soft);
	/* Two lines, then ellipsis, so the grid stays even. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.pt-card__price {
	font-size: var(--pt-text-base);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-snug);
}

.pt-card__price del {
	color: var(--pt-muted);
	font-weight: 400;
	text-decoration-thickness: 1px;
	margin-right: var(--pt-space-2);
}

.pt-card__price ins {
	text-decoration: none;
	color: var(--pt-sale);
}

.pt-badge {
	position: absolute;
	top: var(--pt-space-3);
	left: var(--pt-space-3);
	z-index: 2;
	padding: 0.25rem 0.5rem;
	font-size: var(--pt-text-2xs);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	border-radius: var(--pt-radius-sm);
	background: var(--pt-ink);
	color: var(--pt-paper);
}

.pt-badge--sale { background: var(--pt-sale); }
.pt-badge--out  { background: var(--pt-surface-deep); color: var(--pt-ink-soft); }

/* -------------------------------------------------------------- buttons */

.pt-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--pt-space-2);
	padding: 0.8125rem 1.5rem;
	border: 1px solid transparent;
	border-radius: var(--pt-radius-full);
	font-size: var(--pt-text-sm);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-snug);
	text-decoration: none;
	background: var(--pt-ink);
	color: var(--pt-paper);
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		color var(--pt-fast) var(--pt-ease),
		border-color var(--pt-fast) var(--pt-ease);
}

.pt-btn:hover {
	background: var(--pt-bronze-deep);
	color: var(--pt-paper);
}

.pt-btn--accent { background: var(--pt-bronze); }
.pt-btn--accent:hover { background: var(--pt-bronze-deep); }

.pt-btn--quiet {
	background: transparent;
	border-color: var(--pt-line-strong);
	color: var(--pt-ink);
}

.pt-btn--quiet:hover {
	background: var(--pt-ink);
	color: var(--pt-paper);
	border-color: var(--pt-ink);
}

.pt-btn--block {
	display: flex;
	width: 100%;
}

.pt-btn svg { width: 18px; height: 18px; flex: none; }

/* ------------------------------------------------------------------ header */

.pt-header {
	position: sticky;
	top: 0;
	z-index: 50;
	/* Solid white against the stone ground, so the bar reads as its own surface.
	   No backdrop-filter: an opaque background makes the blur invisible while
	   still costing a compositing layer on every scroll. */
	background: var(--pt-card);
	border-bottom: 1px solid var(--pt-line);
}

.pt-header__inner {
	display: flex;
	align-items: center;
	gap: var(--pt-space-5);
	min-height: 72px;
	padding-block: var(--pt-space-3);
}

.pt-header__brand img {
	height: clamp(22px, 2.2vw, 32px);
	width: auto;
}

/*
 * Bigger on a phone. The desktop size is set against a nine-item nav sharing
 * the row; on mobile the logo has the whole left side to itself and was sitting
 * smaller than the icons opposite it.
 */
@media (max-width: 1200px) {
	.pt-header__brand img { height: 34px; }
}

@media (max-width: 480px) {
	.pt-header__brand img { height: 30px; }
}

/* Below the widest breakpoints the labels step down a size so nine items still
   fit between the logo and the actions. */
@media (max-width: 1400px) {
	.pt-nav__list a {
		font-size: var(--pt-text-xs);
	}

	.pt-nav__icon {
		width: 14px;
		height: 14px;
	}

}

/*
 * The nav takes the space between the logo and the actions and centres itself
 * within it, rather than sitting flush against the logo.
 */
.pt-nav {
	flex: 1;
	display: flex;
	justify-content: center;
	min-width: 0;
}

.pt-header__actions {
	display: flex;
	align-items: center;
	gap: var(--pt-space-2);
}

.pt-iconbtn {
	position: relative;
	display: grid;
	place-items: center;
	width: 42px;
	aspect-ratio: 1;
	background: transparent;
	border: 1px solid transparent;
	border-radius: var(--pt-radius-full);
	color: var(--pt-ink);
	transition: background-color var(--pt-fast) var(--pt-ease);
}

.pt-iconbtn:hover {
	background: var(--pt-surface-deep);
}

.pt-iconbtn svg {
	width: 20px;
	height: 20px;
}

/*
 * The count is refreshed by WooCommerce's fragment AJAX, so it arrives wrapped
 * in a span it owns. That wrapper was an in-flow grid item, which gave the
 * button a second row and pushed the icon 5px above centre. Taking it out of
 * flow leaves the icon as the only thing being centred.
 */
.pt-cart-fragment {
	position: absolute;
	inset: 0;
	pointer-events: none;
}

.pt-cart-count {
	position: absolute;
	top: 1px;
	right: -1px;
	/* A ring in the header's own white, so the badge stays legible where it
	   overlaps the bag beneath it. */
	box-shadow: 0 0 0 2px var(--pt-card);
	min-width: 18px;
	height: 18px;
	padding-inline: 4px;
	display: grid;
	place-items: center;
	font-size: 0.625rem;
	font-weight: 700;
	line-height: 1;
	border-radius: var(--pt-radius-full);
	background: var(--pt-bronze);
	color: oklch(0.99 0 0);
}

/*
 * Nudged 3px left, on the glyph rather than the button, so the icon shifts
 * without moving the hit area or reopening the gap between the three buttons.
 * It buys a little air between the bag and the badge sitting over its corner.
 */
.pt-cart-toggle svg {
	transform: translateX(-3px);
}

/* Navigation */

.pt-nav__list {
	display: flex;
	align-items: center;
	/*
	 * Tight, because a centred nine-item menu between a logo and the action
	 * icons has very little room to spare. Loosens on wide screens.
	 */
	gap: clamp(0.5rem, 1.1vw, 1.5rem);
}

.pt-nav__list a {
	font-size: var(--pt-text-sm);
	font-weight: 500;
	letter-spacing: var(--pt-tracking-snug);
	text-decoration: none;
	white-space: nowrap;
}

/*
 * Only plain-dropdown parents get a positioning context. Mega items are left
 * static on purpose so their panel resolves against the sticky header instead,
 * which lets it span the full width without spilling past the viewport edge —
 * positioning it against the item pushed right-hand panels off-screen and
 * created horizontal overflow, since hidden elements still extend scroll width.
 */
.pt-nav__item--parent:not(.pt-nav__item--mega) {
	position: relative;
}

.pt-nav__link {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	padding-block: var(--pt-space-3);
}

.pt-nav__item.is-current > .pt-nav__link {
	color: var(--pt-bronze-deep);
}

/* ------------------------------------------------------- emphasised links */

.pt-nav__link--icon {
	gap: 0.4rem;
}

.pt-nav__icon {
	flex: none;
	width: 16px;
	height: 16px;
}

/*
 * A rule and extra space before the first emphasised item, separating the
 * browse links from the promotional ones.
 *
 * Expressed as "an emphasised item that follows a normal one", so it lands in
 * the right place even if the menu is reordered, and never draws twice when two
 * emphasised items sit together.
 */
.pt-nav__item:not(.pt-nav__item--emphasis) + .pt-nav__item--emphasis {
	margin-left: clamp(0.5rem, 1.2vw, 1.25rem);
	padding-left: clamp(0.75rem, 1.4vw, 1.5rem);
	border-left: 1px solid var(--pt-line);
}

/* Both promotional links are pills. Filled reads as primary, outlined as
   secondary, so they share a shape without competing. */
.pt-nav__item--emphasis > .pt-nav__link {
	padding: 0.4375rem 0.9375rem;
	border: 1px solid transparent;
	border-radius: var(--pt-radius-full);
	font-weight: 600;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		border-color var(--pt-fast) var(--pt-ease),
		color var(--pt-fast) var(--pt-ease);
}

/* Outlined. */
.pt-nav__item--accent > .pt-nav__link {
	border-color: var(--pt-bronze);
	color: var(--pt-bronze-deep);
	background: transparent;
}

.pt-nav__item--accent > .pt-nav__link:hover {
	background: var(--pt-bronze-tint);
	border-color: var(--pt-bronze-deep);
	color: var(--pt-bronze-deep);
}

/* Filled. The loudest thing in the header by design. */
.pt-nav__item--sale > .pt-nav__link {
	background: var(--pt-bronze);
	border-color: var(--pt-bronze);
	color: oklch(0.99 0 0);
}

.pt-nav__item--sale > .pt-nav__link:hover {
	background: var(--pt-bronze-deep);
	border-color: var(--pt-bronze-deep);
	color: oklch(0.99 0 0);
}

/*
 * Below the widest screens the pills and the divider tighten together — between
 * them they add roughly 55px the row cannot spare.
 *
 * This block has to sit after the rules above: media queries add no
 * specificity, so an identical selector earlier in the file simply loses.
 */
@media (max-width: 1400px) {
	.pt-nav__item--emphasis > .pt-nav__link {
		padding-inline: 0.625rem;
	}

	.pt-nav__item:not(.pt-nav__item--emphasis) + .pt-nav__item--emphasis {
		margin-left: 0.4375rem;
		padding-left: 0.625rem;
	}
}

@media (max-width: 1200px) {
	/* The desktop divider is a left border between neighbours in a row. In the
	   stacked panel the two promoted items lead the list instead, so the rule
	   that separates them is drawn under the second of them. */
	.pt-nav__item:not(.pt-nav__item--emphasis) + .pt-nav__item--emphasis {
		margin-left: 0;
		padding-left: 0;
		border-left: 0;
	}
}

/*
 * Kept deliberately faint. Its whole job is to say "there is more here" — it
 * should be findable when looked for and invisible when not, so it sits at low
 * opacity and only comes forward on hover.
 */
.pt-nav__chev {
	flex: none;
	width: 9px;
	height: auto;
	margin-left: 0.0625rem;
	opacity: 0.4;
	transition:
		opacity var(--pt-fast) var(--pt-ease),
		transform var(--pt-med) var(--pt-ease);
}

.pt-nav__item--parent:hover > .pt-nav__link .pt-nav__chev,
.pt-nav__item--parent:focus-within > .pt-nav__link .pt-nav__chev {
	opacity: 0.85;
	transform: translateY(1px);
}

.pt-nav__item--parent[data-open='true'] > .pt-nav__link .pt-nav__chev {
	opacity: 0.85;
	transform: rotate(180deg);
}

/* The toggle button exists for touch and keyboard; pointer devices use hover. */
.pt-nav__toggle {
	display: none;
}

/* ------------------------------------------------------------- mega panel */

/*
 * The panel spans the full viewport width while staying a child of its nav
 * item, so hovering the trigger and moving into the panel is one continuous
 * hover. Positioned against the header, not the item, so the columns line up
 * with the page grid rather than with whichever word was hovered.
 */
/*
 * A hover bridge across the dead space between the nav item and the panel.
 *
 * The nav item ends at its text, but the panel hangs off the bottom of the
 * header — about 19px lower. Moving the mouse down crossed unhovered ground,
 * :hover dropped, and the panel closed before it could be reached. This
 * invisible strip extends the panel's hover area up to meet the item.
 *
 * It only becomes active once the panel is open, since the panel is
 * pointer-events: none at rest.
 */
.pt-mega::before {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	bottom: 100%;
	height: 2rem;
}

.pt-mega {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	transform: translateY(0.4rem);
	z-index: 40;
	background: var(--pt-mega-bg);
	border-top: 1px solid var(--pt-line);
	border-bottom: 1px solid var(--pt-line);
	box-shadow: 0 24px 48px -32px oklch(0.2 0.013 60 / 0.4);
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition:
		opacity var(--pt-med) var(--pt-ease),
		transform var(--pt-med) var(--pt-ease-quart),
		visibility 0s linear var(--pt-med);
}

.pt-nav__item--mega:hover > .pt-mega,
.pt-nav__item--mega:focus-within > .pt-mega,
.pt-nav__item--mega[data-open='true'] > .pt-mega {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	transform: translateY(0);
	transition-delay: 0s;
}

.pt-mega__inner {
	display: grid;
	gap: clamp(1.5rem, 2.5vw, 3rem);
	/*
	 * Deliberately narrower than the page shell. The panel background spans the
	 * full width, but its contents sit in a tighter measure — a menu stretched
	 * to 1680px leaves the columns marooned at opposite ends of the screen.
	 * Tune with --pt-mega-width.
	 */
	width: min(100% - (var(--pt-gutter) * 2), var(--pt-mega-width));
	margin-inline: auto;
	padding-block: clamp(1.5rem, 2.5vw, 2.25rem);
	grid-template-columns: minmax(0, 1fr);
	align-items: start;
}

@media (min-width: 1000px) {
	.pt-mega__inner {
		/* Image on the left at a fixed share, columns take the rest. */
		grid-template-columns: minmax(200px, 17rem) minmax(0, 1fr);
	}
}

.pt-mega__cols {
	display: grid;
	gap: clamp(1rem, 2vw, 2.5rem);
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.pt-mega__col {
	min-width: 0;
}

.pt-mega__heading {
	display: block;
	margin-bottom: var(--pt-space-3);
	padding-bottom: var(--pt-space-2);
	border-bottom: 1px solid var(--pt-line-strong);
	font-size: var(--pt-text-2xs) !important;
	font-weight: 600 !important;
	letter-spacing: var(--pt-tracking-wider);
	text-transform: uppercase;
	/* A step darker than --pt-muted. On the panel's tinted ground, muted fell to
	   4.08:1, under the 4.5:1 minimum for text this size. */
	color: oklch(0.47 0.012 65);
	white-space: normal !important;
}

.pt-mega__heading:hover {
	color: var(--pt-ink);
}

/*
 * Icon beside a column heading.
 *
 * The heading is uppercase and letterspaced, so the icon is aligned on the cap
 * height rather than the baseline — sitting it on the baseline leaves it
 * looking dropped against all-caps text.
 */
.pt-mega__heading--icon {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

.pt-mega__icon {
	flex: none;
	width: 17px;
	height: 17px;
	color: var(--pt-bronze);
	opacity: 0.85;
	transition: opacity var(--pt-fast) var(--pt-ease);
}

.pt-mega__heading--icon:hover .pt-mega__icon {
	opacity: 1;
}

.pt-mega__heading--highlight .pt-mega__icon {
	opacity: 1;
}

/* A solo item reads as a link, so its icon steps back to match. */
.pt-mega__col--solo .pt-mega__icon {
	width: 15px;
	height: 15px;
	color: var(--pt-muted);
}

.pt-mega__col--solo .pt-mega__heading:hover .pt-mega__icon {
	color: var(--pt-bronze);
}

.pt-mega__heading--highlight {
	color: var(--pt-bronze-deep);
	border-bottom-color: var(--pt-bronze);
}

/*
 * A second-level item with no children is a plain link, not a column heading.
 * The rule underneath would be separating it from nothing, so it reads as a
 * link instead.
 */
.pt-mega__col--solo .pt-mega__heading {
	border-bottom: 0;
	padding-bottom: 0;
	margin-bottom: 0;
	text-transform: none;
	letter-spacing: var(--pt-tracking-snug);
	font-size: var(--pt-text-sm) !important;
	font-weight: 400 !important;
	color: var(--pt-ink-soft);
}

.pt-mega__col--solo .pt-mega__heading:hover {
	color: var(--pt-bronze-deep);
}

.pt-mega__links {
	display: grid;
	gap: var(--pt-space-2);
	list-style: none;
	margin: 0;
	padding: 0;
}

/*
 * Bullets.
 *
 * A drawn dot rather than list-style, so it can be positioned, coloured and
 * animated. Each row is a two-column grid — marker, then link — which keeps the
 * dot aligned to the first line when a long name wraps, instead of drifting to
 * the vertical centre as an inline marker would.
 */
.pt-mega__links > li {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	align-items: start;
	column-gap: 0.625rem;
}

.pt-mega__links > li::before {
	content: '';
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: var(--pt-line-strong);
	/* Sits on the optical centre of the first line, so it holds position when
	   the link wraps. */
	margin-top: 0.52em;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		transform var(--pt-fast) var(--pt-ease);
}

.pt-mega__links > li:hover::before {
	background: var(--pt-bronze);
	transform: scale(1.5);
}

/* The link shifts a touch on hover, so the row reads as one moving object
   rather than a dot and a word behaving separately. */
.pt-mega__link {
	transition:
		color var(--pt-fast) var(--pt-ease),
		transform var(--pt-fast) var(--pt-ease);
}

.pt-mega__links > li:hover .pt-mega__link {
	transform: translateX(2px);
}

/*
 * Split columns, for lists long enough that one strip runs past the panel.
 *
 * CSS multi-column rather than grid: it fills top to bottom before starting the
 * next column, so an alphabetical list still reads down the page. A grid would
 * run left to right and scramble the order.
 *
 * The column itself spans extra tracks so the halves are readable rather than
 * two very narrow strips.
 */
.pt-mega__col--split-2 .pt-mega__links,
.pt-mega__col--split-3 .pt-mega__links {
	display: block;
	column-gap: clamp(1rem, 2vw, 2rem);
}

.pt-mega__col--split-2 .pt-mega__links { column-count: 2; }
.pt-mega__col--split-3 .pt-mega__links { column-count: 3; }

.pt-mega__col--split-2 .pt-mega__links > li,
.pt-mega__col--split-3 .pt-mega__links > li {
	/* Stop a link being torn across the column break. */
	break-inside: avoid;
	margin-bottom: var(--pt-space-2);
}

@media (min-width: 1000px) {
	.pt-mega__col--split-2 { grid-column: span 2; }
	.pt-mega__col--split-3 { grid-column: span 3; }
}

.pt-mega__link {
	display: inline-block;
	font-size: var(--pt-text-sm) !important;
	font-weight: 400 !important;
	color: var(--pt-ink-soft);
	white-space: normal !important;
	transition: color var(--pt-fast) var(--pt-ease);
}

.pt-mega__link:hover {
	color: var(--pt-bronze-deep);
}

/* ---------------------------------------------------------- panel feature */

.pt-mega__feature {
	position: relative;
	display: block;
	overflow: hidden;
	border-radius: var(--pt-radius-lg);
	background: var(--pt-surface-deep);
	/* Square. A portrait panel made the whole menu unnecessarily tall, and the
	   columns rarely need that much height to sit beside. */
	aspect-ratio: 1;
	text-decoration: none;
	isolation: isolate;
}

.pt-mega__feature-media {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transform: scale(1.01);
	transition: transform var(--pt-slow) var(--pt-ease-quart);
	z-index: -1;
}

.pt-mega__feature:hover .pt-mega__feature-media {
	transform: scale(1.06);
}

.pt-mega__feature::after {
	content: '';
	position: absolute;
	inset: 30% 0 0;
	z-index: -1;
	background: linear-gradient(
		to bottom,
		oklch(0.2 0.013 60 / 0) 0%,
		oklch(0.19 0.013 60 / 0.5) 55%,
		oklch(0.18 0.013 60 / 0.84) 100%
	);
}

.pt-mega__feature-body {
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	display: grid;
	gap: 0.35rem;
	padding: clamp(1rem, 1.6vw, 1.5rem);
	color: oklch(0.99 0 0);
}

.pt-mega__feature-heading {
	font-size: var(--pt-text-lg);
	font-weight: 700;
	line-height: 1.15;
	letter-spacing: var(--pt-tracking-tight);
	white-space: normal;
}

.pt-mega__feature-text {
	font-size: var(--pt-text-xs);
	color: oklch(0.99 0 0 / 0.82);
	white-space: normal;
}

.pt-mega__feature-cta {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	margin-top: var(--pt-space-2);
	font-size: var(--pt-text-2xs);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
}

.pt-mega__feature-cta svg {
	width: 11px;
	height: 11px;
	transition: transform var(--pt-fast) var(--pt-ease);
}

.pt-mega__feature:hover .pt-mega__feature-cta svg {
	transform: translate(2px, -2px);
}

/* --------------------------------------------------- plain dropdown fallback */

.pt-subnav {
	position: absolute;
	top: 100%;
	left: 0;
	z-index: 40;
	min-width: 13rem;
	display: grid;
	gap: 2px;
	padding: var(--pt-space-3);
	margin: 0;
	list-style: none;
	background: var(--pt-card);
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius);
	box-shadow: 0 18px 36px -26px oklch(0.2 0.013 60 / 0.4);
	opacity: 0;
	visibility: hidden;
	transform: translateY(0.4rem);
	transition:
		opacity var(--pt-fast) var(--pt-ease),
		transform var(--pt-fast) var(--pt-ease),
		visibility 0s linear var(--pt-fast);
}

.pt-nav__item--parent:not(.pt-nav__item--mega):hover > .pt-subnav,
.pt-nav__item--parent:not(.pt-nav__item--mega):focus-within > .pt-subnav,
.pt-nav__item--parent[data-open='true'] > .pt-subnav {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
	transition-delay: 0s;
}

.pt-subnav__link {
	display: block;
	padding: 0.4rem 0.6rem;
	border-radius: var(--pt-radius-sm);
	font-size: var(--pt-text-sm) !important;
	font-weight: 400 !important;
	color: var(--pt-ink-soft);
	white-space: normal !important;
}

.pt-subnav__link:hover {
	background: var(--pt-surface);
	color: var(--pt-ink);
}

/*
 * The menu scrim. Hidden outright unless the panel is open — the `hidden`
 * attribute is toggled in script, and this makes sure it never intercepts a
 * click on desktop where the nav is an ordinary row.
 */
.pt-navscrim {
	position: fixed;
	inset: 0;
	z-index: 110;
	background: oklch(0.2 0.013 60 / 0.42);
}

.pt-navscrim[hidden] { display: none; }

/* Only the slide-out panel has a close button. */
.pt-nav__close { display: none; }

/*
 * Carries .pt-iconbtn so it is the same 42px square as search and cart.
 *
 * It used to be a 36x24 button of its own, which left the three centres 50px,
 * 50px and 47px apart — the edge gaps matched but the buttons did not, so the
 * row read as unevenly spaced.
 */
.pt-header__burger {
	display: none;
}

.pt-burger {
	display: grid;
	gap: 4.5px;
	width: 19px;
}

.pt-burger span {
	display: block;
	height: 1.6px;
	background: currentColor;
	border-radius: 2px;
}

@media (max-width: 1200px) {
	.pt-header__burger { display: grid; }

	/*
	 * Push the icons to the right edge.
	 *
	 * On desktop the nav sits between logo and actions with flex: 1 and eats
	 * the slack. Below the breakpoint the nav is position: fixed and leaves the
	 * flow entirely, so nothing did — the actions simply sat one gap after the
	 * logo. At 375px that was invisible because logo + gap + icons happened to
	 * fill the row exactly; at any wider phone the slack showed.
	 */
	.pt-header__actions { margin-inline-start: auto; }

	/*
	 * A panel down the right-hand side rather than a full-screen takeover.
	 *
	 * 70% leaves a strip of the page showing, which is both the way back out —
	 * tapping it closes the panel — and a reminder that the page is still
	 * there underneath. Capped so it does not become an absurdly wide menu on
	 * a large tablet.
	 */
	.pt-nav {
		position: fixed;
		inset: 0 0 0 auto;
		z-index: 120;
		width: min(80%, 460px);
		background: var(--pt-card);
		border-left: 1px solid var(--pt-line);
		padding: var(--pt-space-6) var(--pt-space-5) var(--pt-space-8);
		display: block;
		overflow-y: auto;
		overscroll-behavior: contain;
		box-shadow: -24px 0 60px oklch(0.2 0.013 60 / 0.16);
		transform: translateX(100%);
		visibility: hidden;
		transition:
			transform var(--pt-med) var(--pt-ease-quart),
			visibility var(--pt-med) var(--pt-ease-quart);
	}

	.pt-nav[data-open='true'] {
		transform: translateX(0);
		visibility: visible;
	}

	.pt-nav__close {
		display: grid;
		place-items: center;
		width: 38px;
		height: 38px;
		margin: 0 0 var(--pt-space-4) auto;
		padding: 0;
		border: 1px solid var(--pt-line);
		border-radius: var(--pt-radius-full);
		background: none;
		color: var(--pt-ink);
		cursor: pointer;
	}

	.pt-nav__close:hover {
		background: var(--pt-surface-deep);
		border-color: var(--pt-line-strong);
	}

	/*
	 * The two promoted items lead the list as buttons.
	 *
	 * `order` rather than reordering the menu itself: the running order in the
	 * admin is the desktop order, where these two belong at the end after a
	 * divider. Only the stacked panel wants them first.
	 */
	.pt-nav__item--accent { order: -2; }
	.pt-nav__item--sale { order: -1; }

	.pt-nav__item--emphasis {
		border-bottom: 0;
		margin-bottom: var(--pt-space-2);
	}

	/*
	 * `flex`, not the inline-flex the row uses. Inline-flex sizes to its text,
	 * so the two buttons came out 147px and 132px wide inside a 251px column —
	 * two different widths, neither filling the panel.
	 */
	.pt-nav__item--emphasis > .pt-nav__link {
		display: flex;
		width: 100%;
		justify-content: center;
		padding: 0.875rem 1.25rem;
		border: 1px solid transparent;
		border-radius: var(--pt-radius-full);
		font-size: var(--pt-text-sm);
		font-weight: 700;
		color: var(--pt-paper);
	}

	/*
	 * Bronze for New Arrivals, ink for Sale Items — two filled buttons that are
	 * plainly different destinations rather than one control split in two.
	 *
	 * bronze-deep rather than bronze: paper text on the lighter bronze measures
	 * 3.3:1, which is below the 4.5:1 needed at this size. The deep tone reads
	 * as the same brand colour and clears it at 5.4:1.
	 */
	.pt-nav__item--accent > .pt-nav__link {
		background: var(--pt-bronze-deep);
		border-color: var(--pt-bronze-deep);
	}

	.pt-nav__item--sale > .pt-nav__link {
		background: var(--pt-ink);
		border-color: var(--pt-ink);
	}

	/* The last promoted item carries the rule that separates them from the
	   ordinary categories below. */
	.pt-nav__item--sale {
		padding-bottom: var(--pt-space-4);
		margin-bottom: var(--pt-space-4);
		border-bottom: 1px solid var(--pt-line);
	}

	.pt-nav__list {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
	}

	.pt-nav__item {
		border-bottom: 1px solid var(--pt-line);
	}

	.pt-nav__link {
		padding-block: var(--pt-space-4);
		font-size: var(--pt-text-lg);
	}

	/* Chevron is replaced by a real button, so the parent link still navigates
	   while the button opens the panel. Tapping a parent link on mobile should
	   go to that category, not trap you in an accordion. */
	.pt-nav__chev { display: none; }

	.pt-nav__item--parent {
		position: relative;
	}

	.pt-nav__toggle {
		display: block;
		position: absolute;
		top: 0;
		right: 0;
		width: 3.25rem;
		height: 3.5rem;
		background: transparent;
		border: 0;
		color: var(--pt-ink-soft);
	}

	.pt-nav__toggle::before,
	.pt-nav__toggle::after {
		content: '';
		position: absolute;
		top: 50%;
		left: 50%;
		width: 13px;
		height: 1.6px;
		background: currentColor;
		border-radius: 2px;
		transform: translate(-50%, -50%);
		transition: transform var(--pt-fast) var(--pt-ease);
	}

	.pt-nav__toggle::after {
		transform: translate(-50%, -50%) rotate(90deg);
	}

	.pt-nav__item[data-open='true'] .pt-nav__toggle::after {
		transform: translate(-50%, -50%) rotate(0deg);
	}

	/* Panels and dropdowns collapse into the flow rather than overlaying. */
	.pt-mega,
	.pt-subnav {
		position: static;
		width: auto;
		max-width: none;
		transform: none;
		opacity: 1;
		visibility: visible;
		pointer-events: auto;
		border: 0;
		border-radius: 0;
		box-shadow: none;
		background: transparent;
		padding: 0;
		display: none;
		transition: none;
	}

	.pt-nav__item[data-open='true'] > .pt-mega,
	.pt-nav__item[data-open='true'] > .pt-subnav {
		display: block;
		padding-bottom: var(--pt-space-4);
	}

	.pt-mega__inner {
		display: block;
		width: auto;
		padding-block: 0;
	}

	.pt-mega__cols {
		display: grid;
		grid-template-columns: 1fr;
		gap: var(--pt-space-4);
	}

	.pt-mega__heading {
		margin-bottom: var(--pt-space-2);
	}

	.pt-mega__links {
		gap: var(--pt-space-1);
		padding-left: var(--pt-space-2);
	}

	.pt-mega__link,
	.pt-subnav__link {
		display: block;
		padding-block: 0.3rem;
		font-size: var(--pt-text-base) !important;
	}

	/* The panel image is decorative on a phone and costs a lot of scrolling. */
	.pt-mega__feature { display: none; }
}

/* Search bar */

.pt-searchbar {
	border-top: 1px solid var(--pt-line);
	background: var(--pt-surface);
}

.pt-searchbar[hidden] { display: none; }

.pt-searchbar__form {
	display: flex;
	gap: var(--pt-space-3);
	width: min(100% - (var(--pt-gutter) * 2), 720px);
	margin-inline: auto;
	padding-block: var(--pt-space-4);
}

.pt-searchbar__input {
	flex: 1;
	padding: 0.8125rem 1.125rem;
	background: var(--pt-paper);
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius-full);
}

.pt-searchbar__input::placeholder { color: var(--pt-muted); }

/* ---------------------------------------------------------------- sections */

.pt-main {
	padding-block: clamp(2rem, 5vw, 4rem) var(--pt-space-9);
}

/*
 * A full-bleed hero meets the header directly, with no band of paper between
 * them. The top padding exists to keep ordinary page content off the header, so
 * it is dropped only when the hero is the thing sitting against it.
 */
.pt-main:has(> .pt-hero:first-child) {
	padding-top: 0;
}

.pt-section + .pt-section {
	margin-top: var(--pt-space-9);
}

/* WooCommerce emits ul.products; map it onto the theme grid. */
ul.products {
	display: grid;
	gap: clamp(1rem, 2vw, 2rem) clamp(0.75rem, 1.5vw, 1.5rem);
	grid-template-columns: repeat(2, minmax(0, 1fr));
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 640px) {
	ul.products { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 1100px) {
	ul.products { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

ul.products li.product {
	width: auto !important;
	margin: 0 !important;
	float: none !important;
	clear: none !important;
}

.pt-card__media {
	position: relative;
	display: block;
	text-decoration: none;
}

.pt-card__imagelink {
	display: block;
	text-decoration: none;
}

/*
 * Hover actions.
 *
 * Revealed on hover on pointer devices, and on keyboard focus, so they are
 * reachable without a mouse. Not rendered on touch at all — see the (hover:
 * none) rule at the end of this block.
 */
.pt-card__actions {
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	z-index: 2;
	display: flex;
	gap: var(--pt-space-2);
	padding: var(--pt-space-3);
}

.pt-cardbtn {
	flex: 1;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
	min-width: 0;
	padding: 0.625rem 0.75rem;
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-full);
	background: var(--pt-card);
	color: var(--pt-ink);
	font-size: var(--pt-text-xs);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-snug);
	line-height: 1;
	text-decoration: none;
	white-space: nowrap;
	box-shadow: 0 6px 18px -10px oklch(0.2 0.013 60 / 0.45);
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		color var(--pt-fast) var(--pt-ease),
		border-color var(--pt-fast) var(--pt-ease);
}

.pt-cardbtn svg {
	flex: none;
	width: 15px;
	height: 15px;
}

.pt-cardbtn span {
	overflow: hidden;
	text-overflow: ellipsis;
}

.pt-cardbtn:hover,
.pt-cardbtn:focus-visible {
	background: var(--pt-ink);
	border-color: var(--pt-ink);
	color: var(--pt-paper);
}

.pt-cardbtn--view:hover,
.pt-cardbtn--view:focus-visible {
	background: var(--pt-bronze);
	border-color: var(--pt-bronze);
	color: oklch(0.99 0 0);
}

/* WooCommerce marks the button "added" and appends its own View cart link. */
.pt-cardbtn.loading {
	opacity: 0.65;
	pointer-events: none;
}

.pt-cardbtn.added::after {
	content: '';
}

.pt-card__actions .added_to_cart {
	display: none;
}

/* Pointer devices: hide until the card is hovered or something inside it is
   focused, so the product photograph is unobstructed at rest. */
@media (hover: hover) and (pointer: fine) {
	.pt-card__actions {
		opacity: 0;
		transform: translateY(0.5rem);
		transition:
			opacity var(--pt-med) var(--pt-ease),
			transform var(--pt-med) var(--pt-ease);
	}

	.pt-card:hover .pt-card__actions,
	.pt-card:focus-within .pt-card__actions {
		opacity: 1;
		transform: translateY(0);
	}
}

/*
 * Touch: dropped entirely.
 *
 * These are a hover affordance. With no hover to reveal them they sat
 * permanently across the bottom of every card, which on a phone-sized tile
 * covered most of the photograph — the one thing the card exists to show.
 *
 * Nothing is lost by removing them: tapping the card opens the product, where
 * there is a full-size quantity stepper and Add to cart. A cramped icon-only
 * button over the picture was never the better way to buy on a phone.
 */
@media (hover: none) {
	.pt-card__actions {
		display: none;
	}
}

/*
 * Narrow pointer screens — a desktop window dragged small — still get the
 * buttons on hover, but two labels will not fit, so the icons carry it.
 */
@media (hover: hover) and (max-width: 520px) {
	.pt-cardbtn {
		padding: 0.5rem;
	}

	/* Label hidden, icon carries the meaning. The aria-label on the anchor keeps
	   it announced to screen readers. */
	.pt-cardbtn span {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
	}
}

/* Cards fill their grid cell so a row of them lines up regardless of how many
   lines each product name wraps to. */
ul.products li.product,
.pt-products > .pt-card {
	display: flex;
	flex-direction: column;
}

.pt-card__name a {
	text-decoration: none;
}

.pt-card__name a:hover {
	color: var(--pt-bronze-deep);
}

/* ------------------------------------------------------------------ footer */

/* ----------------------------------------------------------------- footer */

.pt-footer {
	padding-top: clamp(2.5rem, 5vw, 4.5rem);
	background: var(--pt-surface-deep);
	border-top: 1px solid var(--pt-line);
}

/*
 * Full site width, matching every other band on the page.
 *
 * The emptiness this band used to read with was a column-count problem, not a
 * width one: four columns across 1329px gave each list more room than it had
 * content for. Five narrower columns and tighter gutters fill the same measure.
 */
.pt-footer__inner {
	display: grid;
	gap: var(--pt-space-6);
	grid-template-columns: 1fr;
	padding-bottom: var(--pt-space-8);
}

@media (min-width: 640px) {
	.pt-footer__inner {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--pt-space-7) var(--pt-space-6);
	}

	.pt-footer__brand { grid-column: 1 / -1; }
}

@media (min-width: 1100px) {
	.pt-footer__inner {
		/*
		 * Brand and Visit carry prose and addresses, so they take the wider
		 * shares; the three link columns need only their longest label.
		 */
		grid-template-columns:
			minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr)
			minmax(0, 1fr) minmax(0, 1.35fr);
		gap: clamp(1.75rem, 2.4vw, 2.5rem);
	}

	.pt-footer__brand { grid-column: auto; }
}


.pt-footer__brand img {
	height: 28px;
	width: auto;
	margin-bottom: var(--pt-space-3);
}

.pt-footer__meta {
	font-size: var(--pt-text-2xs);
	letter-spacing: var(--pt-tracking-wider);
	text-transform: uppercase;
	color: var(--pt-muted);
	margin-bottom: var(--pt-space-4);
}

.pt-footer__blurb,
.pt-footer__note {
	font-size: var(--pt-text-sm);
	color: var(--pt-ink-soft);
	max-width: 34ch;
}

.pt-footer__heading {
	font-size: var(--pt-text-2xs);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-wider);
	text-transform: uppercase;
	color: var(--pt-muted);
	margin-bottom: var(--pt-space-4);
}

.pt-footer__list {
	display: grid;
	gap: var(--pt-space-3);
	list-style: none;
	margin: 0;
	padding: 0;
}

.pt-footer__list a {
	font-size: var(--pt-text-sm);
	text-decoration: none;
	color: var(--pt-ink-soft);
	transition: color var(--pt-fast) var(--pt-ease);
}

.pt-footer__list a:hover { color: var(--pt-bronze-deep); }

/*
 * Category rows carry the same icon set as the mega menu, so a category reads
 * the same wherever it appears. The icon sits inside the anchor: it is part of
 * the link, not decoration beside it, so it lights up on hover with the label.
 */
.pt-footer__list--icon a {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 0.5rem;
	align-items: start;
}

.pt-footer__caticon {
	width: 15px;
	height: 15px;
	/* Optical centre of the first line, so it holds when a label wraps. */
	margin-top: 0.18em;
	color: var(--pt-muted);
	transition: color var(--pt-fast) var(--pt-ease);
}

.pt-footer__list--icon a:hover .pt-footer__caticon { color: var(--pt-bronze); }

/*
 * The Help column has no icons to align to, so it gets the same dot the mega
 * menu uses for its deepest level — enough to bind the list into a column
 * without competing with the icon lists either side of it.
 */
.pt-footer__list--bullet > li {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 0.5rem;
	align-items: start;
}

.pt-footer__list--bullet > li::before {
	content: '';
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: var(--pt-line-strong);
	margin-top: 0.55em;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		transform var(--pt-fast) var(--pt-ease);
}

.pt-footer__list--bullet > li:hover::before {
	background: var(--pt-bronze);
	transform: scale(1.5);
}

/*
 * Delivery and payment, under the blurb. Two lines of fact rather than filler:
 * they give the brand column the height its neighbours have, and they answer
 * the two questions a footer actually gets asked.
 */
ul.pt-footer__assure {
	display: grid;
	gap: var(--pt-space-2);
	list-style: none;
	margin: var(--pt-space-6) 0 0;
	padding: 0;
	max-width: 34ch;
}

.pt-footer__assure > li {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 0.5rem;
	align-items: start;
	font-size: var(--pt-text-xs);
	color: var(--pt-muted);
}

/* Contact rows: icon, then text, with the icon holding the first line. */
.pt-footer__list--contact > li {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 0.5rem;
	align-items: start;
	font-size: var(--pt-text-sm);
	color: var(--pt-ink-soft);
}

.pt-footer__icon {
	width: 15px;
	height: 15px;
	margin-top: 0.2em;
	color: var(--pt-muted);
	flex: none;
}

/* Showroom: name, address and its own numbers as one block. */
.pt-showroom__address {
	display: block;
	text-decoration: none;
	color: var(--pt-ink-soft);
	line-height: 1.45;
}

.pt-showroom__address:hover { color: var(--pt-bronze-deep); }

.pt-showroom__name {
	display: block;
	font-size: var(--pt-text-2xs);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	color: var(--pt-muted);
	margin-bottom: 0.15rem;
}

.pt-showroom__phones {
	display: flex;
	flex-wrap: wrap;
	gap: 0 var(--pt-space-3);
	margin-top: 0.35rem;
}

.pt-showroom__phones a {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	font-size: var(--pt-text-sm);
	font-variant-numeric: tabular-nums;
	text-decoration: none;
	color: var(--pt-ink-soft);
}

.pt-showroom__phones a:hover { color: var(--pt-bronze-deep); }

/* Smaller than the column icons: this one marks a number, it does not head a
   row, and at 15px it read as a second bullet level. */
.pt-showroom__phoneicon {
	width: 12px;
	height: 12px;
	color: var(--pt-muted);
	flex: none;
	transition: color var(--pt-fast) var(--pt-ease);
}

.pt-showroom__phones a:hover .pt-showroom__phoneicon { color: var(--pt-bronze); }

/* The Visit column carries more per row than the link columns, so it breathes. */
.pt-footer__list--contact { gap: var(--pt-space-4); }

/* Social */

/*
 * Set off from the text above and below it. The buttons are 38px objects in a
 * column of 20px text lines, so the type-scale rhythm reads as crowding against
 * them — they need their own breathing room, above and below.
 *
 * Qualified with `ul` on purpose: the `ul[class]` reset near the top of this
 * file is (0,1,1), so a bare `.pt-social` loses the margin outright and the
 * icons sit flush against the paragraphs either side.
 */
ul.pt-social {
	display: flex;
	gap: var(--pt-space-2);
	list-style: none;
	margin-block: var(--pt-space-6);
	margin-inline: 0;
	padding: 0;
}

.pt-social__link {
	display: grid;
	place-items: center;
	width: 38px;
	height: 38px;
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius-full);
	color: var(--pt-ink-soft);
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		border-color var(--pt-fast) var(--pt-ease),
		color var(--pt-fast) var(--pt-ease);
}

.pt-social__link svg {
	width: 17px;
	height: 17px;
}

.pt-social__link:hover {
	background: var(--pt-ink);
	border-color: var(--pt-ink);
	color: var(--pt-paper);
}

.pt-footer__base {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--pt-space-3);
	padding-block: var(--pt-space-5);
	border-top: 1px solid var(--pt-line);
	font-size: var(--pt-text-xs);
	color: var(--pt-muted);
}

.pt-footer__base p { margin: 0; max-width: none; }

/* Credit */

.pt-footer__credit {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
}

.pt-credit {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	font-weight: 500;
	text-decoration: none;
	color: var(--pt-ink-soft);
	transition: color var(--pt-fast) var(--pt-ease);
}

.pt-credit:hover { color: var(--pt-bronze-deep); }

.pt-credit__mark {
	width: 13px;
	height: 13px;
	position: relative;
	top: 1px;
}

/* ------------------------------------------------------------------- misc */

.pt-empty {
	padding-block: var(--pt-space-9);
	text-align: center;
}

.pt-empty p {
	margin-inline: auto;
}

.pt-empty .pt-btn {
	margin-top: var(--pt-space-5);
}

.pt-page__head {
	margin-bottom: var(--pt-space-6);
	padding-bottom: var(--pt-space-5);
	border-bottom: 1px solid var(--pt-line);
}

.pt-page__title {
	font-size: var(--pt-text-3xl);
}

.pt-page__sub {
	margin-top: var(--pt-space-2);
	font-size: var(--pt-text-2xs);
	font-weight: 500;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	color: var(--pt-muted);
}

.pt-postlist {
	display: grid;
	gap: var(--pt-space-6);
	max-width: 70ch;
}

.pt-post__title {
	font-size: var(--pt-text-xl);
}

.pt-post__title a { text-decoration: none; }

/* ---------------------------------------------------------- archive header */

.pt-crumbs {
	display: flex;
	flex-wrap: wrap;
	gap: var(--pt-space-2);
	font-size: var(--pt-text-xs);
	color: var(--pt-muted);
	margin-bottom: var(--pt-space-5);
}

/*
 * Hidden on a phone. A wrapped four-level trail cost two lines above the fold
 * and duplicated the back button; the categories are still one tap away in the
 * menu, and the trail remains for wider screens and for search engines reading
 * the desktop markup.
 */
@media (max-width: 899.98px) {
	.pt-crumbs { display: none; }
}

.pt-crumbs a { text-decoration: none; }
.pt-crumbs a:hover { color: var(--pt-bronze-deep); }

.pt-archive-head {
	margin-bottom: var(--pt-space-7);
}

/* -------------------------------------------------------- category banner */

/*
 * The banner is a wide image with the heading sitting on it. Source images are
 * 16:9, which is far too tall for a page header, so the frame is a shallower
 * band and object-fit crops it — the generation prompt keeps the subject to the
 * right and the left third clear, so the text always lands on quiet pixels.
 */
.pt-banner {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	border-radius: var(--pt-radius-lg);
	background: var(--pt-surface-deep);
	margin-bottom: var(--pt-space-6);
	/*
	 * min-height rather than a hard aspect-ratio: the banner now carries the
	 * heading, count, description and subcategory pills, and a category with
	 * many children would otherwise have them clipped. The ratios below are the
	 * floor, and content grows the band when it needs to.
	 */
	display: flex;
	min-height: min(78vw, 26rem);
}

@media (min-width: 700px) {
	.pt-banner { min-height: min(42vw, 24rem); }
}

@media (min-width: 1200px) {
	.pt-banner { min-height: 24rem; }
}

.pt-banner__media {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	z-index: -1;
}

/* Scrim reads left-to-right so the text side darkens and the product side stays
   bright. Flipped on narrow screens where the text sits at the bottom. */
.pt-banner::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(
		to top,
		oklch(0.18 0.013 60 / 0.82) 0%,
		oklch(0.19 0.013 60 / 0.5) 45%,
		oklch(0.2 0.013 60 / 0.1) 100%
	);
}

@media (min-width: 700px) {
	.pt-banner::after {
		background: linear-gradient(
			to right,
			oklch(0.18 0.013 60 / 0.78) 0%,
			oklch(0.19 0.013 60 / 0.52) 42%,
			oklch(0.2 0.013 60 / 0.12) 72%,
			oklch(0.2 0.013 60 / 0) 100%
		);
	}
}

.pt-banner__inner {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: end;
	width: 100%;
	padding: clamp(1.25rem, 3vw, 3rem);
	color: oklch(0.99 0 0);
}

@media (min-width: 700px) {
	.pt-banner__inner {
		justify-content: center;
		max-width: 52ch;
	}
}

.pt-banner__inner .pt-archive-title {
	color: inherit;
	margin-bottom: var(--pt-space-2);
}

.pt-banner__inner .pt-archive-count {
	color: oklch(0.99 0 0 / 0.8);
	margin-top: 0;
}

.pt-banner__intro {
	margin-top: var(--pt-space-3);
	max-width: 52ch;
	font-size: var(--pt-text-sm);
	color: oklch(0.99 0 0 / 0.86);
}

.pt-banner__intro p { max-width: none; }

.pt-crumbs--on-banner {
	color: oklch(0.99 0 0 / 0.75);
	margin-bottom: var(--pt-space-3);
}

.pt-crumbs--on-banner a { color: inherit; }
.pt-crumbs--on-banner a:hover { color: oklch(0.99 0 0); }

/*
 * Chips on the banner. Frosted rather than solid: a solid light pill would sit
 * on the photograph like a sticker, where a translucent one lets the image read
 * through and keeps the banner feeling like a single surface.
 */
.pt-chips--on-banner {
	margin-top: var(--pt-space-5);
}

.pt-chips--on-banner .pt-chip {
	background: oklch(0.99 0 0 / 0.14);
	border-color: oklch(0.99 0 0 / 0.34);
	color: oklch(0.99 0 0);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
}

.pt-chips--on-banner .pt-chip:hover {
	background: oklch(0.99 0 0);
	border-color: oklch(0.99 0 0);
	color: var(--pt-ink);
}

.pt-chips--on-banner .pt-chip__n {
	color: oklch(0.99 0 0 / 0.7);
}

.pt-chips--on-banner .pt-chip:hover .pt-chip__n {
	color: var(--pt-muted);
}

.pt-archive-title {
	font-size: var(--pt-text-3xl);
}

.pt-archive-count {
	font-size: var(--pt-text-2xs);
	font-weight: 500;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	color: var(--pt-muted);
	margin-top: var(--pt-space-2);
}

.pt-archive-intro {
	max-width: 70ch;
	margin-top: var(--pt-space-4);
	color: var(--pt-ink-soft);
}

/* WooCommerce's ordering select */
.pt-archive-sort select,
.woocommerce-ordering select {
	padding: 0.625rem 2.25rem 0.625rem 1rem;
	background: var(--pt-paper);
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius-full);
	font-size: var(--pt-text-sm);
	appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 5l3 3 3-3' stroke='%23555' stroke-width='1.4' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 0.875rem center;
	background-size: 12px;
}

/* Subcategory chips */
.pt-chips {
	display: flex;
	flex-wrap: wrap;
	gap: var(--pt-space-2);
	margin-top: var(--pt-space-5);
}

.pt-chip {
	display: inline-flex;
	align-items: center;
	gap: var(--pt-space-2);
	padding: 0.4375rem 0.875rem;
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-full);
	background: var(--pt-surface);
	font-size: var(--pt-text-sm);
	text-decoration: none;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		border-color var(--pt-fast) var(--pt-ease);
}

.pt-chip:hover {
	background: var(--pt-bronze-tint);
	border-color: var(--pt-bronze);
	color: var(--pt-ink);
}

.pt-chip__n {
	font-size: var(--pt-text-2xs);
	color: var(--pt-muted);
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------ single product */

/*
 * Named areas rather than source order, because the three blocks want a
 * different arrangement at each size: stacked with the name and price leading
 * on a phone, and the gallery beside a right-hand column on a desktop.
 */
.pt-product__layout {
	display: grid;
	gap: clamp(1.5rem, 4vw, 4rem);
	row-gap: var(--pt-space-5);
	align-items: start;
	grid-template-areas:
		'head'
		'gallery'
		'buy';
}

.pt-product__head { grid-area: head; }
.pt-gallery { grid-area: gallery; }
.pt-buy { grid-area: buy; }

@media (min-width: 900px) {
	.pt-product__layout {
		grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
		grid-template-areas:
			'gallery head'
			'gallery buy';
	}

	.pt-buy {
		position: sticky;
		top: 100px;
	}
}

.pt-gallery__main {
	margin-bottom: var(--pt-space-3);
}

.pt-gallery__thumbs {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
	gap: var(--pt-space-2);
}

.pt-gallery__thumb {
	padding: 0;
	border: 1px solid var(--pt-line);
	background: var(--pt-card);
	cursor: pointer;
	transition: border-color var(--pt-fast) var(--pt-ease);
}

.pt-gallery__thumb:hover { border-color: var(--pt-line-strong); }

.pt-gallery__thumb.is-active {
	border-color: var(--pt-bronze);
	box-shadow: 0 0 0 1px var(--pt-bronze);
}

.pt-buy__sku {
	font-size: var(--pt-text-2xs);
	font-weight: 500;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	color: var(--pt-muted);
	margin-bottom: var(--pt-space-3);
}

.pt-buy__title {
	font-size: var(--pt-text-2xl);
	margin-bottom: var(--pt-space-4);
}

.pt-buy__price {
	font-size: var(--pt-text-xl);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-snug);
	margin-bottom: var(--pt-space-5);
}

.pt-buy__price del {
	color: var(--pt-muted);
	font-weight: 400;
	margin-right: var(--pt-space-2);
}

.pt-buy__price ins {
	text-decoration: none;
	color: var(--pt-sale);
}

.pt-buy__stock--out {
	display: inline-block;
	padding: 0.3125rem 0.75rem;
	border-radius: var(--pt-radius-full);
	background: var(--pt-surface-deep);
	color: var(--pt-ink-soft);
	font-size: var(--pt-text-xs);
	font-weight: 600;
	margin-bottom: var(--pt-space-4);
}

.pt-buy__summary {
	color: var(--pt-ink-soft);
	margin-bottom: var(--pt-space-5);
}

/* WooCommerce's add-to-cart form */
.pt-buy form.cart {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--pt-space-3);
	margin: 0;
}

.pt-buy .quantity input[type='number'] {
	width: 5.5rem;
	padding: 0.8125rem 0.75rem;
	text-align: center;
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius-full);
	background: var(--pt-paper);
}

.pt-buy button[type='submit'],
.pt-buy .single_add_to_cart_button {
	flex: 1 1 12rem;
	padding: 0.9375rem 1.75rem;
	border: 0;
	border-radius: var(--pt-radius-full);
	background: var(--pt-ink);
	color: var(--pt-paper);
	font-size: var(--pt-text-sm);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-snug);
	transition: background-color var(--pt-fast) var(--pt-ease);
}

.pt-buy button[type='submit']:hover,
.pt-buy .single_add_to_cart_button:hover {
	background: var(--pt-bronze-deep);
}

.pt-product__details {
	margin-top: var(--pt-space-8);
	padding-top: var(--pt-space-6);
	border-top: 1px solid var(--pt-line);
}

.pt-prose {
	max-width: 72ch;
	color: var(--pt-ink-soft);
}

/*
 * The product description runs the full container rather than the 72ch measure
 * used for editorial pages.
 *
 * 72ch exists because a line much longer than that is hard to track back to the
 * start of the next one. These descriptions are short specification paragraphs
 * rather than prose to be read end to end, so the width buys scanability here
 * where it would cost readability on a policy page.
 */
.pt-product__details .pt-prose,
.pt-product__details .pt-prose p,
.pt-product__details .pt-prose li {
	max-width: none;
}

.pt-prose > * + * { margin-top: var(--pt-space-4); }

.related.products,
.upsells.products {
	margin-top: var(--pt-space-8);
	padding-top: var(--pt-space-6);
	border-top: 1px solid var(--pt-line);
}

.related.products > h2,
.upsells.products > h2 {
	font-size: var(--pt-text-2xl);
	margin-bottom: var(--pt-space-6);
}

/* ------------------------------------------------------------- pagination */

/*
 * WooCommerce styles its pager with selectors like
 *
 *   .woocommerce nav.woocommerce-pagination ul li a          (0,2,4)
 *   .woocommerce nav.woocommerce-pagination ul li span.current (0,3,4)
 *
 * which outrank anything written as `.woocommerce-pagination a`. The theme's
 * previous rules here lost every declaration that mattered: the pills stayed
 * `display: block` with a 1em min-width, so they rendered as tall ovals rather
 * than circles, and the current page kept WooCommerce's lavender — including
 * its low-contrast purple numeral.
 *
 * So the overrides below mirror WooCommerce's own selector shape rather than
 * trying to outgun it. Equal specificity, and app.css is enqueued with
 * woocommerce-general as a dependency, so it loads second and wins the tie.
 * Ordinary WordPress pagination is handled by the plainer selectors, which
 * nothing competes with.
 */

.woocommerce-pagination,
.pt-main .navigation.pagination {
	margin-top: var(--pt-space-8);
}

/* Base — also covers non-WooCommerce archives, where nothing outranks it. */
.woocommerce-pagination ul,
.pagination .nav-links {
	display: flex;
	flex-wrap: wrap;
	gap: var(--pt-space-2);
	justify-content: center;
	list-style: none;
	margin: 0;
	padding: 0;
	border: 0;
}

.woocommerce-pagination ul li,
.pagination .nav-links li {
	border: 0;
	margin: 0;
	padding: 0;
}

.woocommerce-pagination a,
.woocommerce-pagination span,
.pagination .page-numbers {
	display: grid;
	place-items: center;
	min-width: 42px;
	height: 42px;
	padding-inline: 0.75rem;
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-full);
	background: var(--pt-paper);
	font-size: var(--pt-text-sm);
	font-weight: 500;
	line-height: 1;
	color: var(--pt-ink);
	text-decoration: none;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		border-color var(--pt-fast) var(--pt-ease),
		color var(--pt-fast) var(--pt-ease);
}

/* The WooCommerce-shaped overrides. Selector shape matched on purpose. */
.woocommerce nav.woocommerce-pagination ul {
	display: flex;
	border: 0;
	margin: 0;
	white-space: normal;
}

.woocommerce nav.woocommerce-pagination ul li {
	float: none;
	display: block;
	/* WooCommerce clips each item; a rounded pill inside a clipped box loses
	   its corners. */
	overflow: visible;
	border-right: 0;
}

.woocommerce nav.woocommerce-pagination ul li a,
.woocommerce nav.woocommerce-pagination ul li span {
	display: grid;
	place-items: center;
	min-width: 42px;
	height: 42px;
	padding: 0 0.75rem;
	font-size: var(--pt-text-sm);
	font-weight: 500;
	line-height: 1;
}

/*
 * WooCommerce paints hover, focus and current with the same lavender, so all
 * three have to be answered — otherwise hovering any number turns it the colour
 * that is supposed to mean "you are here".
 */
.woocommerce nav.woocommerce-pagination ul li a:hover,
.woocommerce nav.woocommerce-pagination ul li a:focus,
.pagination .page-numbers:not(.current):not(.dots):hover {
	background: var(--pt-surface-deep);
	border-color: var(--pt-line-strong);
	color: var(--pt-ink);
}

.woocommerce nav.woocommerce-pagination ul li span.current,
.pagination .page-numbers.current {
	background: var(--pt-ink);
	border-color: var(--pt-ink);
	color: var(--pt-paper);
}

/* The ellipsis is a gap in the sequence, not a destination — so it is not
   dressed as something clickable. */
.woocommerce nav.woocommerce-pagination ul li span.dots,
.pagination .page-numbers.dots {
	background: none;
	border-color: transparent;
	color: var(--pt-muted);
	min-width: 1.5rem;
	padding-inline: 0;
}

/* ------------------------------------------------------------ cart drawer */

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

.pt-drawer {
	position: fixed;
	inset: 0;
	z-index: 100;
}

.pt-drawer__scrim {
	position: absolute;
	inset: 0;
	background: oklch(0.20 0.013 60 / 0.42);
	opacity: 0;
	transition: opacity var(--pt-med) var(--pt-ease);
}

.pt-drawer[data-open='true'] .pt-drawer__scrim { opacity: 1; }

.pt-drawer__panel {
	position: absolute;
	inset-block: 0;
	inset-inline-end: 0;
	/* Matches the menu panel: a strip of page stays visible, and its scrim is
	   already wired to close on tap. */
	width: min(80%, 460px);
	display: flex;
	flex-direction: column;
	background: var(--pt-paper);
	box-shadow: -24px 0 60px oklch(0.20 0.013 60 / 0.16);
	transform: translateX(100%);
	transition: transform var(--pt-med) var(--pt-ease-quart);
}

.pt-drawer[data-open='true'] .pt-drawer__panel { transform: translateX(0); }

.pt-drawer__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--pt-space-4);
	padding: var(--pt-space-5);
	border-bottom: 1px solid var(--pt-line);
}

.pt-drawer__title {
	font-size: var(--pt-text-lg);
	font-weight: 700;
	letter-spacing: var(--pt-tracking-snug);
}

.pt-drawer__body {
	flex: 1;
	display: flex;
	flex-direction: column;
	min-height: 0;
	overflow-y: auto;
}

/* Mini cart */

/*
 * Selector is `ul.pt-minicart`, not `.pt-minicart`. The reset near the top of
 * this file uses `ul[class]`, which carries the same weight as a class — so a
 * bare `.pt-minicart` loses the padding fight to the theme's own reset.
 */
ul.pt-minicart {
	flex: 1;
	list-style: none;
	margin: 0;
	padding: var(--pt-space-5);
	display: grid;
	gap: var(--pt-space-5);
	align-content: start;
}

.pt-minicart__item {
	position: relative;
	display: grid;
	grid-template-columns: 76px minmax(0, 1fr);
	gap: var(--pt-space-4);
	align-items: start;
	padding-bottom: var(--pt-space-5);
	border-bottom: 1px solid var(--pt-line);
}

.pt-minicart__item:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

.pt-minicart__media {
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius);
}

.pt-minicart__info {
	display: grid;
	gap: var(--pt-space-3);
	min-width: 0;
	/* Leave room for the remove button, which sits top-right of the row. */
	padding-right: var(--pt-space-6);
}

.pt-minicart__name {
	font-size: var(--pt-text-sm);
	font-weight: 500;
	line-height: 1.35;
	text-decoration: none;
	color: var(--pt-ink);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.pt-minicart__line {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--pt-space-3);
}

.pt-minicart__qty {
	font-size: var(--pt-text-2xs);
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	color: var(--pt-muted);
}

.pt-minicart__price {
	font-size: var(--pt-text-sm);
	font-weight: 600;
}

.pt-minicart__remove {
	position: absolute;
	top: 0;
	right: 0;
	display: grid;
	place-items: center;
	width: 26px;
	aspect-ratio: 1;
	border-radius: var(--pt-radius-full);
	background: var(--pt-surface-deep);
	color: var(--pt-muted);
	font-size: 1rem;
	line-height: 1;
	text-decoration: none;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		color var(--pt-fast) var(--pt-ease);
}

.pt-minicart__remove:hover {
	background: var(--pt-sale);
	color: oklch(0.99 0 0);
}

.pt-minicart__foot {
	position: sticky;
	bottom: 0;
	padding: var(--pt-space-5);
	background: var(--pt-surface);
	border-top: 1px solid var(--pt-line);
	display: grid;
	gap: var(--pt-space-4);
}

.pt-minicart__total {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--pt-space-4);
	font-size: var(--pt-text-lg);
}

.pt-minicart__total strong {
	font-weight: 700;
	letter-spacing: var(--pt-tracking-snug);
}

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

.pt-minicart__actions {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--pt-space-3);
}

.pt-minicart__empty {
	flex: 1;
	display: grid;
	place-content: center;
	justify-items: center;
	gap: var(--pt-space-4);
	padding: var(--pt-space-7) var(--pt-space-5);
	text-align: center;
	color: var(--pt-muted);
}

body.pt-drawer-open {
	overflow: hidden;
}

/* ------------------------------------------------------- forms & notices */

.pt-main input[type='text'],
.pt-main input[type='email'],
.pt-main input[type='tel'],
.pt-main input[type='password'],
.pt-main input[type='number'],
.pt-main input[type='search'],
.pt-main textarea,
.pt-main select {
	width: 100%;
	padding: 0.75rem 1rem;
	background: var(--pt-paper);
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius);
	font-size: var(--pt-text-sm);
	transition: border-color var(--pt-fast) var(--pt-ease);
}

.pt-main input:focus,
.pt-main textarea:focus,
.pt-main select:focus {
	border-color: var(--pt-bronze);
}

.pt-main textarea { min-height: 7rem; resize: vertical; }

.form-row {
	display: grid;
	gap: var(--pt-space-2);
	margin-bottom: var(--pt-space-4);
}

.form-row label {
	font-size: var(--pt-text-xs);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	color: var(--pt-muted);
}

.required { color: var(--pt-sale); text-decoration: none; }

.woocommerce-message,
.woocommerce-info,
.woocommerce-error {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--pt-space-4);
	padding: var(--pt-space-4) var(--pt-space-5);
	margin-bottom: var(--pt-space-5);
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius);
	background: var(--pt-surface);
	font-size: var(--pt-text-sm);
	list-style: none;
}

.woocommerce-message { background: var(--pt-bronze-tint); border-color: var(--pt-bronze); }
.woocommerce-error { background: color-mix(in oklch, var(--pt-sale) 8%, var(--pt-paper)); border-color: var(--pt-sale); }

.woocommerce-message .button,
.woocommerce-info .button,
.woocommerce-error .button {
	margin-left: auto;
}

/* ------------------------------------------------------------------- cart */

.woocommerce-cart-form { margin-bottom: var(--pt-space-7); }

.shop_table {
	width: 100%;
	border-collapse: collapse;
	border: 0;
	table-layout: auto;
}

.shop_table th {
	padding: var(--pt-space-3);
	border-bottom: 1px solid var(--pt-line-strong);
	font-size: var(--pt-text-2xs);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	color: var(--pt-muted);
	text-align: left;
}

.shop_table td {
	padding: var(--pt-space-4) var(--pt-space-3);
	border-bottom: 1px solid var(--pt-line);
	vertical-align: middle;
}

/* Column sizing: the product name takes the slack, everything else is snug. */
.shop_table th.product-remove,
.shop_table td.product-remove { width: 3rem; padding-left: 0; }

.shop_table th.product-thumbnail,
.shop_table td.product-thumbnail { width: 100px; }

.shop_table th.product-price,
.shop_table td.product-price,
.shop_table th.product-subtotal,
.shop_table td.product-subtotal { text-align: right; white-space: nowrap; }

.shop_table th.product-quantity,
.shop_table td.product-quantity { width: 7rem; }

.shop_table td.product-subtotal { font-weight: 600; }

.shop_table .product-thumbnail img {
	width: 84px;
	height: 84px;
	aspect-ratio: 1;
	object-fit: contain;
	background: var(--pt-card);
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-sm);
}

.shop_table .product-name a {
	text-decoration: none;
	font-weight: 500;
	line-height: 1.35;
}

.shop_table .product-name a:hover { color: var(--pt-bronze-deep); }

.shop_table .product-remove a,
.shop_table .product-remove .remove {
	display: grid;
	place-items: center;
	width: 26px;
	height: 26px;
	border-radius: var(--pt-radius-full);
	background: var(--pt-surface-deep);
	color: var(--pt-muted);
	font-size: 1rem;
	line-height: 1;
	text-decoration: none;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		color var(--pt-fast) var(--pt-ease);
}

.shop_table .product-remove a:hover {
	background: var(--pt-sale);
	color: oklch(0.99 0 0);
}

.shop_table .quantity { display: inline-flex; }

.shop_table .quantity input {
	width: 5rem;
	text-align: center;
	padding: 0.5rem;
}

/* The Update cart row. */
.shop_table td.actions {
	padding: var(--pt-space-5) 0 0;
	border-bottom: 0;
	text-align: right;
}

.shop_table td.actions .button[name='update_cart'][disabled] {
	opacity: 0.45;
	cursor: not-allowed;
}

/*
 * Narrow screens: the six-column table becomes one card per item.
 * WooCommerce puts the column name in data-title on each cell, so those become
 * the labels. This replaces the woocommerce-smallscreen stylesheet, which the
 * theme dequeues because it also carries a conflicting layout system.
 */
@media (max-width: 760px) {
	.shop_table.cart thead { display: none; }

	.shop_table.cart,
	.shop_table.cart tbody { display: block; width: 100%; }

	.shop_table.cart tr.cart_item {
		position: relative;
		display: grid;
		grid-template-columns: 84px minmax(0, 1fr);
		grid-template-areas:
			'thumb name'
			'thumb price'
			'qty   subtotal';
		gap: var(--pt-space-2) var(--pt-space-4);
		align-items: center;
		padding: var(--pt-space-4) 0;
		border-bottom: 1px solid var(--pt-line);
	}

	.shop_table.cart tr.cart_item td {
		display: block;
		width: auto;
		padding: 0;
		border: 0;
		text-align: left;
	}

	.shop_table.cart td.product-thumbnail { grid-area: thumb; }
	.shop_table.cart td.product-name      { grid-area: name; padding-right: 2rem; }
	.shop_table.cart td.product-price     { grid-area: price; }
	.shop_table.cart td.product-quantity  { grid-area: qty; }
	.shop_table.cart td.product-subtotal  { grid-area: subtotal; text-align: right; }

	/* Remove button floats to the top-right of the card. */
	.shop_table.cart td.product-remove {
		position: absolute;
		top: var(--pt-space-4);
		right: 0;
		width: auto;
	}

	/* Show the column name as a small label above the value. */
	.shop_table.cart td.product-price::before,
	.shop_table.cart td.product-subtotal::before {
		content: attr(data-title);
		display: block;
		font-size: var(--pt-text-2xs);
		letter-spacing: var(--pt-tracking-wide);
		text-transform: uppercase;
		color: var(--pt-muted);
		margin-bottom: 2px;
	}

	.shop_table.cart tr:not(.cart_item) { display: block; }
	.shop_table.cart td.actions { display: block; text-align: left; }
	.shop_table.cart td.actions .button { width: 100%; }
}

.cart-collaterals {
	display: flex;
	justify-content: flex-end;
}

.cart_totals {
	width: 100%;
	max-width: 26rem;
	padding: var(--pt-space-5);
	background: var(--pt-surface);
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-lg);
}

.cart_totals h2 {
	font-size: var(--pt-text-xl);
	margin-bottom: var(--pt-space-4);
}

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

.cart_totals th,
.cart_totals td {
	padding: var(--pt-space-3) 0;
	border-bottom: 1px solid var(--pt-line);
	text-align: left;
}

.cart_totals th {
	font-size: var(--pt-text-xs);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	color: var(--pt-muted);
}

.cart_totals td { text-align: right; font-weight: 500; }

.cart_totals .order-total td { font-size: var(--pt-text-lg); font-weight: 700; }

.coupon {
	display: flex;
	gap: var(--pt-space-2);
	margin-bottom: var(--pt-space-4);
}

.coupon input[type='text'] { flex: 1; }

/* --------------------------------------------------------------- checkout */

.woocommerce-checkout .pt-main > .woocommerce { display: block; }

form.checkout {
	display: grid;
	gap: clamp(1.5rem, 4vw, 3.5rem);
	align-items: start;
}

@media (min-width: 900px) {
	/*
	 * Two explicit rows: the heading gets exactly its own height, the review box
	 * takes the rest. Without `grid-template-rows: auto 1fr` the billing column
	 * (which spans both rows) stretched row 1, leaving a large gap between the
	 * "Your order" heading and the box beneath it.
	 */
	form.checkout {
		grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
		grid-template-rows: auto 1fr;
		row-gap: var(--pt-space-5);
	}

	#customer_details    { grid-column: 1; grid-row: 1 / span 2; }
	#order_review_heading { grid-column: 2; grid-row: 1; align-self: end; margin-bottom: 0; }
	#order_review        { grid-column: 2; grid-row: 2; align-self: start; }
}

#customer_details h3 {
	font-size: var(--pt-text-xl);
	margin-bottom: var(--pt-space-5);
}

/*
 * The order-review heading gets no bottom margin: spacing to the box below is
 * the grid's row-gap. Setting both produced double the intended gap.
 */
#order_review_heading {
	font-size: var(--pt-text-xl);
	margin: 0 0 var(--pt-space-4);
}

@media (min-width: 900px) {
	#order_review_heading { margin-bottom: 0; }
}

#order_review {
	padding: var(--pt-space-5);
	background: var(--pt-surface);
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-lg);
}

#order_review .shop_table th,
#order_review .shop_table td {
	padding-block: var(--pt-space-3);
}

.woocommerce-checkout-payment {
	margin-top: var(--pt-space-5);
}

.wc_payment_methods {
	list-style: none;
	margin: 0 0 var(--pt-space-5);
	padding: 0;
	display: grid;
	gap: var(--pt-space-3);
}

.wc_payment_method {
	padding: var(--pt-space-4);
	background: var(--pt-paper);
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius);
}

.wc_payment_method label {
	font-weight: 600;
	cursor: pointer;
}

.payment_box {
	margin-top: var(--pt-space-3);
	padding-top: var(--pt-space-3);
	border-top: 1px solid var(--pt-line);
	font-size: var(--pt-text-sm);
	color: var(--pt-muted);
}

#place_order,
.checkout-button,
.woocommerce .button.alt,
.wc-proceed-to-checkout .button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	padding: 1rem 1.75rem;
	border: 0;
	border-radius: var(--pt-radius-full);
	background: var(--pt-bronze);
	color: oklch(0.99 0 0);
	font-size: var(--pt-text-base);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-snug);
	text-decoration: none;
	transition: background-color var(--pt-fast) var(--pt-ease);
}

#place_order:hover,
.checkout-button:hover,
.wc-proceed-to-checkout .button:hover {
	background: var(--pt-bronze-deep);
}

/* Generic WooCommerce buttons that are not the primary action. */
.woocommerce .button:not(.alt):not(.checkout-button):not(.pt-cardbtn) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.75rem 1.25rem;
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius-full);
	background: var(--pt-paper);
	color: var(--pt-ink);
	font-size: var(--pt-text-sm);
	font-weight: 600;
	text-decoration: none;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		color var(--pt-fast) var(--pt-ease);
}

.woocommerce .button:not(.alt):not(.checkout-button):hover {
	background: var(--pt-ink);
	color: var(--pt-paper);
	border-color: var(--pt-ink);
}

/* Order received / thank-you */

.woocommerce-order {
	max-width: 46rem;
}

.woocommerce-thankyou-order-details {
	display: grid;
	gap: var(--pt-space-4);
	grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
	list-style: none;
	margin: var(--pt-space-6) 0;
	padding: var(--pt-space-5);
	background: var(--pt-surface);
	border-radius: var(--pt-radius-lg);
}

.woocommerce-thankyou-order-details li {
	display: grid;
	gap: var(--pt-space-1);
	font-size: var(--pt-text-lg);
	font-weight: 600;
}

.woocommerce-thankyou-order-details li strong { font-weight: 600; }

.woocommerce-thankyou-order-details li::first-line { font-weight: 400; }

/* ------------------------------------------------------- buy controls */

/*
 * The add-to-cart row: a quantity stepper, then the button taking the rest.
 *
 * WooCommerce ships `form.cart` with a floated quantity box and a button sized
 * by its text, which is why the button used to sit at 412x37 next to an 88x50
 * field — two different heights on one line. Laying the form out here makes the
 * two controls share a height and the button own the leftover width.
 */
.woocommerce div.product form.cart {
	display: flex;
	align-items: stretch;
	gap: var(--pt-space-3);
	/* The three stacked controls share one rhythm; see --pt-buy-gap. */
	margin-block: var(--pt-space-5) var(--pt-buy-gap);
}

/*
 * WooCommerce clears the form's floats with `content: " "` on ::before and
 * ::after. Once the form is a flex container those stop being invisible and
 * become flex items in their own right — each collecting a gap, which inset the
 * row by 12px at both ends and stopped Add to cart lining up with the buttons
 * stacked underneath it. The same clearfix caused the product grid to shift
 * every card one cell along.
 */
.woocommerce div.product form.cart::before,
.woocommerce div.product form.cart::after {
	content: none;
}

/*
 * The stepper, wherever a quantity input appears — product page and cart alike.
 *
 * Specificity is deliberate: `.woocommerce .quantity .qty`, `.shop_table
 * .quantity input` and an older `.pt-buy` rule all set a width, a border and a
 * background on this input, the strongest at (0,3,1). Qualifying with both
 * classes clears them all rather than leaving the field bordered inside an
 * already-bordered pill.
 */
.quantity.pt-qty,
.woocommerce .quantity.pt-qty {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	align-items: center;
	width: 122px;
	height: 46px;
	margin: 0;
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius-full);
	background: var(--pt-card);
	overflow: hidden;
}

.quantity.pt-qty input.qty,
.woocommerce .quantity.pt-qty input.qty,
.woocommerce .quantity.pt-qty input[type='number'] {
	width: 100%;
	height: 100%;
	min-height: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	text-align: center;
	font-size: var(--pt-text-sm);
	font-weight: 600;
	color: var(--pt-ink);
	-moz-appearance: textfield;
	appearance: textfield;
}

/*
 * Qualified with the wrapper class, not bare. A bare `.pt-qty__step` is (0,1,0)
 * and loses to the browser's own button styling in some contexts — in the cart
 * these rendered at the UA default 25x29 with a grey bevel.
 */
.quantity.pt-qty .pt-qty__step {
	display: grid;
	place-items: center;
	width: 40px;
	height: 100%;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	color: var(--pt-ink);
	font-size: 1.15rem;
	font-weight: 400;
	line-height: 1;
	cursor: pointer;
	transition: color var(--pt-fast) var(--pt-ease);
	-webkit-appearance: none;
	appearance: none;
}

.quantity.pt-qty .pt-qty__step:hover { color: var(--pt-bronze-deep); }

.quantity.pt-qty .pt-qty__step:disabled {
	color: var(--pt-muted);
	cursor: default;
}

.quantity.pt-qty input.qty::-webkit-outer-spin-button,
.quantity.pt-qty input.qty::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

.quantity.pt-qty input.qty:focus {
	outline: none;
	box-shadow: none;
}

/* On the product page it grows to match the buy controls beside it. */
.woocommerce div.product form.cart .quantity.pt-qty {
	flex: none;
	width: 132px;
	height: var(--pt-control-h);
}


/*
 * Written with WooCommerce's own selector shape. `.woocommerce a.button.alt`
 * and friends are (0,3,1) and set their own colour, padding and font — a plain
 * `.single_add_to_cart_button` never gets a look in.
 */
.woocommerce div.product form.cart button.single_add_to_cart_button,
.woocommerce div.product form.cart .single_add_to_cart_button.button.alt {
	flex: 1;
	min-width: 0;
	display: grid;
	place-items: center;
	height: var(--pt-control-h);
	padding: 0 var(--pt-space-5);
	border: 1px solid var(--pt-ink);
	border-radius: var(--pt-radius-full);
	background: var(--pt-ink);
	color: var(--pt-paper);
	font-size: var(--pt-text-sm);
	font-weight: 700;
	line-height: 1;
	text-transform: none;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		border-color var(--pt-fast) var(--pt-ease);
}

.woocommerce div.product form.cart button.single_add_to_cart_button:hover,
.woocommerce div.product form.cart .single_add_to_cart_button.button.alt:hover {
	background: var(--pt-bronze-deep);
	border-color: var(--pt-bronze-deep);
	color: var(--pt-paper);
}

/*
 * The two secondary actions stack under the row at the same height as the
 * controls above them, so the buy area reads as one block of three sizes rather
 * than three arbitrary ones.
 */
/*
 * White, not the quiet button's transparent. On the paper ground a transparent
 * button is the same colour as the page and reads as an outline drawn on
 * nothing; white lifts both off it and matches the product cards.
 */
.pt-buy__whatsapp,
.pt-enquiry__open {
	height: var(--pt-control-h);
	margin-bottom: var(--pt-buy-gap);
	background: var(--pt-card);
}

.pt-buy__whatsapp svg { width: 19px; height: 19px; }

.pt-enquiry__icon { width: 18px; height: 18px; }

/*
 * The two stacked buttons hover differently on purpose. Sharing the quiet
 * button's ink fill made them look like one control split in half; giving each
 * its own colour says they go to different places.
 */
.pt-buy__whatsapp:hover,
.pt-buy__whatsapp:focus-visible {
	background: var(--pt-whatsapp);
	border-color: var(--pt-whatsapp);
	color: var(--pt-ink);
}

.pt-enquiry__open:hover,
.pt-enquiry__open:focus-visible {
	background: var(--pt-bronze-deep);
	border-color: var(--pt-bronze-deep);
	color: var(--pt-paper);
}

/* ------------------------------------------------------- buy assurances */

/*
 * Three policy marks, as one quiet panel rather than a row of stacked labels
 * behind a rule.
 *
 * Qualified `ul.pt-assure`, not `.pt-assure`: the `ul[class]` reset near the
 * top of this file is (0,1,1) and beats a bare class, which zeroed the padding
 * and left the icons sitting on the border above them.
 */
ul.pt-assure {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	align-items: center;
	list-style: none;
	margin: var(--pt-space-5) 0 0;
	padding: var(--pt-space-4) var(--pt-space-2);
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-lg);
	background: var(--pt-card);
}

.pt-assure > li {
	display: flex;
	justify-content: center;
	min-width: 0;
}

/* A hairline between columns, not a dotted rule — at this size dots read as
   texture rather than structure. */
.pt-assure > li + li {
	border-left: 1px solid var(--pt-line);
}

.pt-assure__item {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	min-width: 0;
	padding-inline: var(--pt-space-2);
	text-decoration: none;
	color: var(--pt-ink);
	transition: color var(--pt-fast) var(--pt-ease);
}

.pt-assure__icon {
	width: 22px;
	height: 22px;
	flex: none;
	color: var(--pt-bronze);
	transition: color var(--pt-fast) var(--pt-ease);
}

/* One line each. Two-word labels broken over two lines made a 34px-tall row of
   shouting, which is what this replaces. */
.pt-assure__label {
	font-size: var(--pt-text-2xs);
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	white-space: nowrap;
}

a.pt-assure__item:hover,
a.pt-assure__item:focus-visible {
	color: var(--pt-bronze-deep);
}

a.pt-assure__item:hover .pt-assure__icon,
a.pt-assure__item:focus-visible .pt-assure__icon {
	color: var(--pt-bronze-deep);
}

/*
 * Stack when the panel runs out of room — measured against the buy column, not
 * the window.
 *
 * A viewport breakpoint is the wrong instrument here. The buy column is one
 * half of the product layout, so at an 885px window this panel is already down
 * to 334px and the three labels sit at zero headroom, while a `max-width:
 * 620px` media query is still nowhere near firing. A container query asks the
 * only question that matters: is there room for three across?
 */
.pt-buy { container: pt-buy / inline-size; }

@container pt-buy (max-width: 430px) {
	ul.pt-assure {
		grid-template-columns: 1fr;
		padding: var(--pt-space-2) var(--pt-space-4);
	}

	.pt-assure > li {
		justify-content: start;
		padding-block: var(--pt-space-3);
	}

	.pt-assure > li + li {
		border-left: 0;
		border-top: 1px solid var(--pt-line);
	}

	.pt-assure__item { padding-inline: 0; }
}

/* ------------------------------------------------------------------ dialog */

/*
 * Native <dialog>. The element itself is the box; ::backdrop is the ground
 * behind it, which is why the panel inside is what carries the padding — a
 * click landing on the dialog rather than the panel is a backdrop click, and
 * that is what the script closes on.
 */
.pt-dialog {
	width: min(100% - 2rem, 34rem);
	max-height: min(88vh, 46rem);
	padding: 0;
	border: 0;
	border-radius: var(--pt-radius-lg);
	background: var(--pt-card);
	color: var(--pt-ink);
	overflow: auto;
	overscroll-behavior: contain;
}

.pt-dialog::backdrop {
	background: oklch(0.205 0.013 60 / 0.55);
	backdrop-filter: blur(2px);
}

.pt-dialog__panel { padding: clamp(1.25rem, 3vw, 2rem); }

.pt-dialog__head {
	display: flex;
	align-items: start;
	justify-content: space-between;
	gap: var(--pt-space-4);
}

.pt-dialog__title {
	font-size: var(--pt-text-lg);
	font-weight: 700;
	letter-spacing: var(--pt-tracking-tight);
	margin: 0;
}

.pt-dialog__close {
	display: grid;
	place-items: center;
	flex: none;
	width: 34px;
	height: 34px;
	padding: 0;
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-full);
	background: none;
	color: var(--pt-ink);
	cursor: pointer;
	transition:
		background-color var(--pt-fast) var(--pt-ease),
		border-color var(--pt-fast) var(--pt-ease);
}

.pt-dialog__close:hover {
	background: var(--pt-surface-deep);
	border-color: var(--pt-line-strong);
}

.pt-dialog__lede {
	font-size: var(--pt-text-sm);
	color: var(--pt-muted);
	margin: var(--pt-space-2) 0 var(--pt-space-5);
}

/* ---------------------------------------------------------------- enquiry */

.pt-enquiry {
	/* Spacing comes from the button above it; a margin here would stack on top
	   of that one and open a gap twice the size of the others. */
	margin-top: 0;
}

.pt-enquiry__done {
	padding: var(--pt-space-3) var(--pt-space-4);
	margin-bottom: var(--pt-space-4);
	border-radius: var(--pt-radius);
	background: var(--pt-bronze-tint);
	border: 1px solid var(--pt-bronze);
	font-size: var(--pt-text-sm);
}

.pt-enquiry__form {
	margin-top: var(--pt-space-4);
	padding: var(--pt-space-5);
	background: var(--pt-surface);
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-lg);
}

.pt-enquiry__grid {
	display: grid;
	gap: var(--pt-space-3);
}

@media (min-width: 520px) {
	.pt-enquiry__grid { grid-template-columns: 1fr 1fr; }
}

/* Honeypot: present for bots, invisible and unreachable for people. */
.pt-enquiry__hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* ==========================================================================
   WooCommerce overrides
   --------------------------------------------------------------------------
   woocommerce-general is kept for form, notice and account styling, but it
   ships opinionated colours and sizes that beat the theme on specificity —
   its purple buttons and 32px cart thumbnails, for instance. These selectors
   are written to match or exceed WooCommerce's own so the theme wins on merit
   rather than with !important.
   ========================================================================== */

/*
 * Kill WooCommerce's clearfix on product lists.
 *
 * It styles ul.products with ::before / ::after carrying `content: " "` and
 * `display: table` — a float clearfix left over from its float-based layout.
 * Inside a grid container those pseudo-elements become grid items: ::before
 * takes the first cell and shifts every product one place along, which reads as
 * a missing first product on category archives and in Related Products.
 */
.woocommerce ul.products::before,
.woocommerce ul.products::after,
ul.products::before,
ul.products::after,
.woocommerce .related ul.products::before,
.woocommerce .related ul.products::after {
	content: none;
	display: none;
}

/* Cart thumbnails: WooCommerce forces 32px via `.woocommerce table.cart img`. */
.woocommerce table.shop_table td.product-thumbnail img,
.woocommerce table.cart img,
.woocommerce #content table.cart img {
	width: 84px;
	height: 84px;
	max-width: none;
	object-fit: contain;
	background: var(--pt-card);
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-sm);
	box-shadow: none;
}

@media (max-width: 760px) {
	.woocommerce table.shop_table td.product-thumbnail img,
	.woocommerce table.cart img {
		width: 84px;
		height: 84px;
	}
}

/* Primary actions. WooCommerce paints these #7f54b3. */
.woocommerce a.button.alt,
.woocommerce button.button.alt,
.woocommerce input.button.alt,
.woocommerce #respond input#submit.alt,
.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover,
.woocommerce input.button.alt:hover,
.woocommerce #place_order,
.woocommerce .wc-proceed-to-checkout a.checkout-button {
	background: var(--pt-bronze);
	color: oklch(0.99 0 0);
	border-radius: var(--pt-radius-full);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-snug);
	text-shadow: none;
	border: 0;
}

.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover,
.woocommerce input.button.alt:hover,
.woocommerce #place_order:hover,
.woocommerce .wc-proceed-to-checkout a.checkout-button:hover {
	background: var(--pt-bronze-deep);
	color: oklch(0.99 0 0);
}

/*
 * Secondary buttons: Update cart, Apply coupon, Continue shopping.
 *
 * Product-card buttons are excluded. They need WooCommerce's `.button` class so
 * its AJAX add-to-cart binds to them, but that class also drags in this rule's
 * display and padding — which pushed the icon onto its own line above the label.
 * Excluding them keeps the behaviour without the styling.
 */
.woocommerce a.button:not(.pt-cardbtn),
.woocommerce button.button:not(.pt-cardbtn),
.woocommerce input.button:not(.pt-cardbtn),
.woocommerce #respond input#submit {
	padding: 0.6875rem 1.25rem;
	background: var(--pt-card);
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius-full);
	color: var(--pt-ink);
	font-size: var(--pt-text-sm);
	font-weight: 600;
	text-shadow: none;
}

.woocommerce a.button:not(.pt-cardbtn):hover,
.woocommerce button.button:not(.pt-cardbtn):hover,
.woocommerce input.button:not(.pt-cardbtn):hover {
	background: var(--pt-ink);
	border-color: var(--pt-ink);
	color: var(--pt-paper);
}

/*
 * Card buttons, restated to out-weigh WooCommerce's own rules.
 *
 * The selector to beat is `.woocommerce ul.products li.product .button` at
 * (0,4,2), which sets display:inline-block. Because these buttons are flex
 * items their display is blockified, so inline-block resolved to block and
 * stacked the icon above the label. Adding li.product and the a element takes
 * this to (0,4,3), which wins.
 */
.woocommerce ul.products li.product a.pt-cardbtn,
.woocommerce a.pt-cardbtn,
.pt-card__actions a.pt-cardbtn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
	/* WooCommerce gives loop buttons margin-top: 1em, which left Add to cart
	   sitting 12px lower than View. The row spacing comes from the container. */
	margin: 0;
	padding: 0.625rem 0.75rem;
	border: 1px solid var(--pt-line);
	border-radius: var(--pt-radius-full);
	background: var(--pt-card);
	color: var(--pt-ink);
	font-size: var(--pt-text-xs);
	font-weight: 600;
	line-height: 1;
	white-space: nowrap;
	text-shadow: none;
}

.woocommerce ul.products li.product a.pt-cardbtn:hover,
.woocommerce ul.products li.product a.pt-cardbtn:focus-visible,
.woocommerce a.pt-cardbtn:hover,
.pt-card__actions a.pt-cardbtn:hover {
	background: var(--pt-ink);
	border-color: var(--pt-ink);
	color: var(--pt-paper);
}

.woocommerce ul.products li.product a.pt-cardbtn--view:hover,
.woocommerce ul.products li.product a.pt-cardbtn--view:focus-visible,
.woocommerce a.pt-cardbtn--view:hover,
.pt-card__actions a.pt-cardbtn--view:hover {
	background: var(--pt-bronze);
	border-color: var(--pt-bronze);
	color: oklch(0.99 0 0);
}

.woocommerce button.button:disabled,
.woocommerce button.button:disabled[disabled] {
	opacity: 0.45;
	padding: 0.6875rem 1.25rem;
	color: var(--pt-muted);
}

/* Remove links keep WooCommerce's red on hover only. */
.woocommerce a.remove {
	color: var(--pt-muted) !important;
	font-weight: 400;
}

.woocommerce a.remove:hover {
	background: var(--pt-sale) !important;
	color: oklch(0.99 0 0) !important;
}

/* Notices: WooCommerce draws a thick coloured top border and a tick pseudo. */
.woocommerce .woocommerce-message,
.woocommerce .woocommerce-info,
.woocommerce .woocommerce-error,
.woocommerce-message,
.woocommerce-info,
.woocommerce-error {
	border-top-width: 1px;
	padding-left: var(--pt-space-5);
}

.woocommerce .woocommerce-message::before,
.woocommerce .woocommerce-info::before,
.woocommerce .woocommerce-error::before {
	display: none;
}

/* Price colours: WooCommerce tints these green. */
.woocommerce div.product p.price,
.woocommerce div.product span.price,
.woocommerce ul.products li.product .price {
	color: inherit;
	font-size: inherit;
}

.woocommerce ul.products li.product .price del { color: var(--pt-muted); }
.woocommerce ul.products li.product .price ins { color: var(--pt-sale); background: none; }

/* Totals tables. */
.woocommerce table.shop_table {
	border: 0;
	border-radius: 0;
	border-collapse: collapse;
}

.woocommerce table.shop_table td,
.woocommerce table.shop_table th {
	border-top: 0;
}

.woocommerce-cart .cart_totals table.shop_table td,
.woocommerce-cart .cart_totals table.shop_table th {
	padding: var(--pt-space-3) 0;
}

/* Quantity input: WooCommerce sizes this for its own layout. */
.woocommerce .quantity .qty {
	width: 5rem;
	padding: 0.5rem;
	text-align: center;
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius);
	background: var(--pt-paper);
}

/* Checkout payment box: WooCommerce gives it a grey fill and an arrow. */
.woocommerce-checkout #payment {
	background: transparent;
	border-radius: 0;
}

.woocommerce-checkout #payment div.payment_box {
	background: var(--pt-surface);
	border-radius: var(--pt-radius);
	color: var(--pt-ink-soft);
	font-size: var(--pt-text-sm);
}

.woocommerce-checkout #payment div.payment_box::before {
	display: none;
}

.woocommerce-checkout #payment ul.payment_methods {
	border-bottom: 0;
	padding: 0;
}

/* Form fields inside WooCommerce screens. */
.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select,
.woocommerce .select2-container .select2-selection--single {
	padding: 0.75rem 1rem;
	height: auto;
	min-height: 0;
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius);
	background: var(--pt-paper);
	line-height: 1.5;
}

.woocommerce .select2-container .select2-selection--single .select2-selection__rendered {
	line-height: 1.5;
	padding: 0;
}

.woocommerce .select2-container .select2-selection--single .select2-selection__arrow {
	top: 50%;
	transform: translateY(-50%);
}

.woocommerce form .form-row label {
	font-size: var(--pt-text-xs);
	font-weight: 600;
	letter-spacing: var(--pt-tracking-wide);
	text-transform: uppercase;
	color: var(--pt-muted);
}

/* ------------------------------------------------------ checkout form layout */

/*
 * WooCommerce lays these out with percentage floats. Grid is steadier and lets
 * the paired fields (phone / alternate phone) sit side by side without the
 * clearfix dance.
 */
.woocommerce form .form-row {
	display: grid;
	gap: var(--pt-space-2);
	margin: 0 0 var(--pt-space-4);
	padding: 0;
	float: none;
	width: auto;
}

.woocommerce .woocommerce-billing-fields__field-wrapper,
.woocommerce .woocommerce-additional-fields__field-wrapper {
	display: grid;
	grid-template-columns: 1fr;
	gap: 0 var(--pt-space-4);
}

@media (min-width: 560px) {
	.woocommerce .woocommerce-billing-fields__field-wrapper {
		grid-template-columns: 1fr 1fr;
	}

	.woocommerce .woocommerce-billing-fields__field-wrapper .form-row-wide,
	.woocommerce .woocommerce-billing-fields__field-wrapper #billing_address_1_field,
	.woocommerce .woocommerce-billing-fields__field-wrapper #billing_address_2_field {
		grid-column: 1 / -1;
	}

	/*
	 * Phone and alternate phone read as a pair, so they share a row. Targeted by
	 * ID because WooCommerce reapplies form-row-wide to the phone field when the
	 * "required" setting is used, overwriting any class set via the field filter.
	 */
	.woocommerce .woocommerce-billing-fields__field-wrapper #billing_phone_field,
	.woocommerce .woocommerce-billing-fields__field-wrapper #billing_alternate_phone_field {
		grid-column: auto;
	}
}

.woocommerce form .form-row-first,
.woocommerce form .form-row-last,
.woocommerce form .form-row-wide {
	float: none;
	width: auto;
	margin-right: 0;
}

/* Field hints, e.g. under the alternate phone. */
.woocommerce form .form-row .description,
.woocommerce form .form-row span.description {
	font-size: var(--pt-text-xs);
	font-weight: 400;
	letter-spacing: normal;
	text-transform: none;
	color: var(--pt-muted);
	background: none;
	border: 0;
	padding: 0;
	margin: 0;
}

.woocommerce form .form-row .description::before { display: none; }

/* Order notes. */
.woocommerce .woocommerce-additional-fields {
	margin-top: var(--pt-space-6);
	padding-top: var(--pt-space-6);
	border-top: 1px solid var(--pt-line);
}

.woocommerce .woocommerce-additional-fields h3 {
	font-size: var(--pt-text-lg);
	margin-bottom: var(--pt-space-4);
}

.woocommerce form .form-row textarea,
.woocommerce #order_comments {
	display: block;
	width: 100%;
	min-height: 7.5rem;
	padding: 0.875rem 1rem;
	background: var(--pt-paper);
	border: 1px solid var(--pt-line-strong);
	border-radius: var(--pt-radius);
	font-family: inherit;
	font-size: var(--pt-text-sm);
	line-height: 1.6;
	resize: vertical;
	transition: border-color var(--pt-fast) var(--pt-ease);
}

.woocommerce form .form-row textarea::placeholder {
	color: var(--pt-muted);
}

.woocommerce form .form-row textarea:focus {
	border-color: var(--pt-bronze);
	outline: none;
	box-shadow: 0 0 0 3px color-mix(in oklch, var(--pt-bronze) 18%, transparent);
}

/* Validation states. */
.woocommerce form .form-row.woocommerce-invalid input.input-text,
.woocommerce form .form-row.woocommerce-invalid select,
.woocommerce form .form-row.woocommerce-invalid textarea {
	border-color: var(--pt-sale);
}

.woocommerce form .form-row.woocommerce-validated input.input-text {
	border-color: var(--pt-line-strong);
}

/* ------------------------------------------------------------ money figures */

/*
 * Totals were rendering at weight 900. `<strong>` resolves `bolder` relative to
 * its parent, so a 700 row produced 900 on the amount inside it — and Archivo at
 * 900 is heavy enough to read as a different typeface. Pin every amount to 700
 * and keep figures tabular so columns align.
 */
.woocommerce-Price-amount,
.woocommerce-Price-amount bdi,
.cart_totals .order-total .woocommerce-Price-amount,
.cart_totals .order-total strong,
.cart_totals .order-total strong .woocommerce-Price-amount,
#order_review .order-total .woocommerce-Price-amount,
#order_review .order-total strong,
.pt-minicart__total strong,
.pt-buy__price,
.pt-card__price {
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	font-feature-settings: 'tnum' 1;
	letter-spacing: var(--pt-tracking-snug);
}

/* Line-item amounts sit a step lighter than the totals they add up to. */
.shop_table td.product-price .woocommerce-Price-amount,
.pt-minicart__price .woocommerce-Price-amount,
#order_review td .woocommerce-Price-amount {
	font-weight: 500;
}

.shop_table td.product-subtotal .woocommerce-Price-amount,
#order_review .order-total .woocommerce-Price-amount {
	font-weight: 700;
}

/*
 * The PKR sign is noticeably wider than the digits beside it, so give it a
 * little breathing room and stop it inheriting the heavy weight.
 */
.woocommerce-Price-currencySymbol {
	font-weight: 500;
	padding-right: 0.06em;
}

/* --------------------------------------------------- category tiles on /shop/ */

/*
 * The shop page is configured to list categories rather than products, matching
 * the live site. WooCommerce emits li.product-category with its own markup, so
 * it gets the same treatment as the home page bento tiles: image, scrim, label
 * over the top.
 */
.woocommerce ul.products li.product-category {
	position: relative;
	overflow: hidden;
	border-radius: var(--pt-radius-lg);
	background: var(--pt-surface-deep);
	aspect-ratio: 4 / 3;
	isolation: isolate;
}

.woocommerce ul.products li.product-category > a {
	display: block;
	height: 100%;
	text-decoration: none;
}

.woocommerce ul.products li.product-category img {
	width: 100%;
	height: 100%;
	margin: 0;
	object-fit: cover;
	transition: transform var(--pt-slow) var(--pt-ease-quart);
}

.woocommerce ul.products li.product-category:hover img {
	transform: scale(1.055);
}

.woocommerce ul.products li.product-category > a::after {
	content: '';
	position: absolute;
	inset: 40% 0 0;
	background: linear-gradient(
		to bottom,
		oklch(0.20 0.013 60 / 0) 0%,
		oklch(0.20 0.013 60 / 0.45) 55%,
		oklch(0.18 0.013 60 / 0.8) 100%
	);
	pointer-events: none;
}

.woocommerce ul.products li.product-category .woocommerce-loop-category__title {
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	z-index: 2;
	margin: 0;
	padding: clamp(0.875rem, 2vw, 1.5rem);
	font-size: clamp(1rem, 1.4vw, 1.4rem);
	font-weight: 700;
	line-height: 1.15;
	letter-spacing: var(--pt-tracking-tight);
	color: oklch(0.99 0 0);
}

.woocommerce ul.products li.product-category .count {
	display: block;
	margin-top: var(--pt-space-1);
	background: none;
	font-size: var(--pt-text-2xs);
	font-weight: 500;
	letter-spacing: var(--pt-tracking-wide);
	color: oklch(0.99 0 0 / 0.82);
}


