/**
 * Single product page.
 *
 * Loaded only on a product — see inc/assets.php.
 *
 * The live product page puts the quantity stepper, an outlined Add To Cart, a
 * filled Buy it now and a square wishlist control on one row, all 50px tall.
 * WooCommerce's add-to-cart block supplies the stepper and the first button;
 * the rest of the row is ours, so the rules below only have to bring the
 * block's own button into line with the two beside it.
 */

.gp-product__byline-row {
	gap: var(--wp--preset--spacing--40);
	margin-block: 6px 0;
}

/* ---------- the buy row ---------- */

/*
 * Two lines, as the live page has it: how many and how many are left, then the
 * three controls that act. The break is made by letting the stock line grow
 * into the rest of the first line, which needs no spacer element and collapses
 * to a single line by itself on a product whose stock is not counted.
 */
/* Doubled to outrank the block-gap WordPress writes onto the group's own
   generated layout class, which is 24px and too wide for a control row. */
.gp-product__buy-row.gp-product__buy-row {
	gap: 10px 12px;
	align-items: center;
	margin-block-start: var(--wp--preset--spacing--40);
	flex-wrap: wrap;
}

/* WooCommerce nests the stepper, the button and the wishlist link three
   wrappers deep — a notices div, the form, then a group. Collapsing those
   wrappers makes all four controls items of this row, which is the only way
   the wishlist heart can be ordered after a Buy it now button that is not its
   sibling. A notice, when there is one, is given the full width so it takes
   its own line rather than joining the row. */
.gp-product__buy-row > .wc-block-components-notices,
.gp-product__buy-row .wc-block-add-to-cart-with-options,
.gp-product__buy-row .wp-block-add-to-cart-with-options,
.gp-product__buy-row .wc-block-add-to-cart-with-options > .wp-block-group {
	display: contents;
}

.gp-product__buy-row .wc-block-components-notice-banner { flex-basis: 100%; }

/* Source order is the accident of three plugins writing into one row: the
   stock line arrives before the stepper it annotates, and the heart before the
   Buy it now it should follow. */
.gp-product__buy-row .wp-block-add-to-cart-with-options-quantity-selector { order: 0; }
.gp-product__buy-row .wc-block-components-product-stock-indicator { order: 1; margin: 0; }
.gp-product__buy-row .wc-block-components-product-button { order: 2; }
.gp-product__buy-row .gp-buy-now { order: 3; }
.gp-product__buy-row .wishsuite-btn { order: 4; }

/* The rest of the first line, less a few pixels of slack: the stepper is 120
   and the gap 12, and asking for the exact remainder leaves the line one
   rounded sub-pixel from overflowing, which drops the stock line onto a row of
   its own. Claiming the space is what leaves the buttons nowhere to go but the
   next line. */
.gp-product__buy-row .wc-block-components-product-stock-indicator {
	display: flex;
	align-items: center;
	gap: 8px;
	flex: 1 1 calc(100% - 140px);
}

/* The live line is ticked. Masked like the basket so the glyph is one colour
   token rather than a second copy of the icon for every state. */
.gp-product__buy-row .wc-block-components-product-stock-indicator::before {
	content: "";
	flex: 0 0 auto;
	inline-size: 20px;
	block-size: 20px;
	background: var(--wp--preset--color--brand-green);
	-webkit-mask: var(--gp-check) center / contain no-repeat;
	mask: var(--gp-check) center / contain no-repeat;
}

/* ---------- the stepper ---------- */

/* 120 x 50 with a green hairline is the live control. The block's own input
   comes out taller than the box that holds it, which is what left the number
   sitting below the − and + beside it, so both parts are given the height
   outright rather than a percentage of a box they are overflowing. */
.gp-product__buy-row .wc-block-components-quantity-selector {
	box-sizing: border-box;
	inline-size: 120px;
	block-size: 50px;
	margin: 0;
	border: 1px solid var(--wp--preset--color--brand-green);
	border-radius: 4px;
	overflow: hidden;
}

.gp-product__buy-row .wc-block-components-quantity-selector__input {
	box-sizing: border-box;
	block-size: 50px;
	min-block-size: 0;
	padding: 0;
	font-size: var(--wp--preset--font-size--base);
	line-height: 1;
	color: #002c22;
}

.gp-product__buy-row .wc-block-components-quantity-selector__button {
	box-sizing: border-box;
	inline-size: 36px;
	block-size: 50px;
	padding: 0;
	font-size: 18px;
	line-height: 1;
	color: #002c22;
}

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

/* The outline half of the pair. !important because WordPress emits the button
   element's own fill from theme.json at a specificity this cannot reach. */
.gp-product__buy-row .wc-block-components-product-button__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	box-sizing: border-box;
	min-inline-size: 210px;
	/* A stated height, not padding plus a line box: the row holds four
	   controls from three different sources and only a shared height lines
	   their edges up. */
	block-size: 50px;
	padding: 0 24px;
	border: 2px solid var(--wp--preset--color--brand-green) !important;
	border-radius: 8px !important;
	background: var(--wp--preset--color--surface) !important;
	color: #002c22 !important;
	font-size: var(--wp--preset--font-size--base);
	font-weight: 400;
	line-height: 1;
}

/* The live button carries a basket beside its label. Drawn as a mask rather
   than a background image so it takes the button's colour and turns white with
   the rest of the label on hover. */
.gp-product__buy-row .wc-block-components-product-button__button::before {
	content: "";
	flex: 0 0 auto;
	inline-size: 20px;
	block-size: 20px;
	background: currentColor;
	-webkit-mask: var(--gp-basket) center / contain no-repeat;
	mask: var(--gp-basket) center / contain no-repeat;
}

.gp-product__buy-row {
	--gp-basket: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8h18l-1.6 11.2a2 2 0 0 1-2 1.8H6.6a2 2 0 0 1-2-1.8Z"/><path d="M8.5 8 12 3l3.5 5"/><path d="M9.5 12v5M14.5 12v5"/></svg>');
	--gp-check: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="m8.5 12.2 2.4 2.4 4.6-4.9"/></svg>');
}

/* Live's hover pair, measured on the live buttons: the outline half goes to
   #121212 with an #e3f0e9 label, the solid half to near-black #040404 with a
   #121212 rule. */
.gp-product__buy-row .wc-block-components-product-button__button:hover {
	background: #121212 !important;
	color: #e3f0e9 !important;
	border-color: #000 !important;
}

/* WooCommerce fades its quantity steppers to 0.6 and brings them back on
   hover; live's steps sit at full ink and do not react. */
.wc-block-components-quantity-selector .wc-block-components-quantity-selector__button,
.wc-block-components-quantity-selector .wc-block-components-quantity-selector__button:hover {
	opacity: 1;
}

/* The live wishlist control is a square, icon only: the word beside the heart
   is what makes the local one twice as wide as the buttons are tall. */
.gp-product__buy-row .wishsuite-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	inline-size: 50px;
	block-size: 50px;
	padding: 0;
	border: 2px solid var(--wp--preset--color--brand-green);
	border-radius: 8px;
	background: transparent;
	/* Live's heart sits at the brand green, not the deeper ink the outline
	   button uses. */
	color: var(--wp--preset--color--brand-green);
	text-decoration: none;
	transition: background-color 200ms ease, color 200ms ease, border-color 200ms ease;
}

/* The one button on the site that does not go to near-black: live fills the
   wishlist control with the brand green and turns the heart white, keeping
   its own green rule. Measured on the live product page. */
.gp-product__buy-row .wishsuite-btn:hover,
.gp-product__buy-row .wishsuite-btn:focus-visible {
	background: var(--wp--preset--color--brand-green);
	color: var(--wp--preset--color--surface);
	border-color: var(--wp--preset--color--brand-green);
	text-decoration: none;
}

/* The plugin colours the glyph itself, so it has to follow the label. */
.gp-product__buy-row .wishsuite-btn:hover svg,
.gp-product__buy-row .wishsuite-btn:hover svg * {
	color: currentColor;
	fill: currentColor;
	stroke: currentColor;
}

@media (prefers-reduced-motion: reduce) {
	.gp-product__buy-row .wishsuite-btn { transition: none; }
}

.gp-product__buy-row .wishsuite-btn .wishsuite-btn-text {
	position: absolute;
	inline-size: 1px;
	block-size: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* ---------- type ---------- */

/*
 * Measured against the live page. The family and its two weights are the same
 * on both sites; what differed was a handful of sizes, and the body line
 * height, which is set in theme.json.
 */

/* 24/600 on a 1.5 line, not the xl preset at the heading weight — a book title
   runs long in Bengali and 28/700 turned two lines into a slab. */
.gp-product__summary h1.wp-block-post-title {
	font-size: 24px;
	font-weight: 600;
	line-height: 1.5;
}

/* The stepper's number, which WooCommerce sizes down to 13px and bolds. Three
   classes because the block's own rule is two and lands later. */
.gp-product__buy-row .wc-block-components-quantity-selector .wc-block-components-quantity-selector__input {
	font-size: var(--wp--preset--font-size--base);
	font-weight: 400;
}

/* Tab labels are a quieter 15/500 on the live page; the panel headings above
   each section are larger and lighter than a theme h3. */
.gp-product-tabs .gp-product-tabs__tab {
	font-size: 15px;
	font-weight: 500;
	line-height: 1.6;
}

.gp-product-tabs .gp-product-tabs__panel h3 {
	font-size: 32px;
	font-weight: 600;
	line-height: 1.1;
}

/* ---------- gallery ---------- */

/* The live gallery has no zoom affordance layered over the cover. */
.gp-gallery__zoom { display: none; }

/* ---------- reviews ---------- */

/*
 * The live reviews section is a header — the count and a way to add one — over
 * a plain list: stars, then who wrote it, then what they said, each entry
 * closed by a rule. WooCommerce's block renders the same three things in a
 * different order and with a floated avatar, so most of what follows is
 * putting its parts where the live page puts them.
 */

.gp-reviews__head {
	gap: var(--wp--preset--spacing--40);
	align-items: flex-start;
	margin-block-end: var(--wp--preset--spacing--50);
}

/* The live heading is a plain 20px line, not a section display heading; the
   block's md preset carries !important, so the size is set on the element. */
.gp-reviews__title {
	margin-block: 0 8px;
	font-size: 20px;
	font-weight: 400;
	line-height: 1.4;
	color: #000;
}

/*
 * The live header is the average as a number, the count beside it, and a way
 * to add one — no stars, which are already on every entry below.
 *
 * WooCommerce has no block for the average on its own (product-average-rating
 * declares no postId context, so it renders nothing in a template), and the
 * rating block wraps the figure in a whole sentence. Collapsing that sentence
 * and restoring the one element holding the number is what is left.
 */
.gp-reviews__score .wc-block-components-product-rating__container {
	display: flex;
	align-items: center;
	gap: 12px;
}

.gp-reviews__score .wc-block-components-product-rating__stars {
	inline-size: auto;
	block-size: auto;
	/* The block sets WooCommerce's icon font here; the number must not use it. */
	font-family: inherit;
	font-size: 0;
}

.gp-reviews__score .wc-block-components-product-rating__stars::before,
.gp-reviews__score .wc-block-components-product-rating__stars > span::before { content: none; }

.gp-reviews__score .wc-block-components-product-rating__stars > span {
	position: static;
	inline-size: auto !important;
	text-indent: 0;
}

.gp-reviews__score .wc-block-components-product-rating__stars strong.rating {
	font-size: 20px;
	font-weight: 700;
	color: #000;
}

.gp-reviews__score .wc-block-components-product-rating__reviews_count,
.gp-reviews__score .wc-block-components-product-rating__reviews_count a {
	font-size: 12px;
	color: rgba(0, 0, 0, 0.7);
	text-decoration: none;
}


/* WooCommerce's reviews block ships its own heading above the list, which
   would repeat the one above it. */
.gp-reviews .wp-block-woocommerce-product-reviews > h2:first-child,
.gp-reviews .woocommerce-Reviews-title { display: none; }

/* ---------- stars ---------- */

/*
 * WooCommerce draws its stars with a webfont loaded by woocommerce-general.css,
 * which this theme dequeues (see inc/assets.php) — without it a rating renders
 * as the sentence "Rated 5 out of 5". The markup underneath is a fixed track
 * with a span whose inline width is the rating as a percentage, so the same
 * effect comes from two rows of ★ and the overflow the span already has.
 */
.gp-reviews .star-rating,
.gp-product__byline-row .wc-block-components-product-rating__stars {
	position: relative;
	display: block;
	overflow: hidden;
	inline-size: 5.6em;
	block-size: 1.15em;
	font-family: inherit;
	font-size: 16px;
	line-height: 1.15;
}

/* Larger in the list than in the byline: there the stars are the entry's
   headline, here they are one fact among several on a line. */
.gp-reviews .star-rating { font-size: 20px; }

.gp-reviews .star-rating::before,
.gp-product__byline-row .wc-block-components-product-rating__stars::before {
	content: "★★★★★";
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	color: rgba(0, 0, 0, 0.18);
	letter-spacing: 0.1em;
}

/* The span carries the inline width; its own text is pushed out of the box
   rather than hidden, so assistive technology still reads it. */
.gp-reviews .star-rating > span,
.gp-product__byline-row .wc-block-components-product-rating__stars > span {
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	display: block;
	overflow: hidden;
	block-size: 100%;
	text-indent: -999em;
	white-space: nowrap;
}

.gp-reviews .star-rating > span::before,
.gp-product__byline-row .wc-block-components-product-rating__stars > span::before {
	content: "★★★★★";
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	color: #057a07;
	letter-spacing: 0.1em;
	text-indent: 0;
}

/* Stars and count sit on the author's line rather than stacking under it. */
.gp-product__byline-row .wc-block-components-product-rating__container {
	display: flex;
	align-items: center;
	gap: 8px;
}

.gp-product__byline-row .wc-block-components-product-rating__reviews_count a {
	color: var(--wp--preset--color--ink);
	text-decoration: none;
}

/* ---------- the list ---------- */

.gp-reviews .commentlist {
	margin: 0;
	padding: 0;
	list-style: none;
}

.gp-reviews .commentlist > li.review {
	padding-block-end: 24px;
	border-block-end: 1px solid rgba(0, 0, 0, 0.2);
}

.gp-reviews .commentlist > li.review + li.review { margin-block-start: 24px; }

/*
 * Source order is stars, avatar, author line, text, with the avatar floated
 * beside all of it. The live entry reads stars across the top, then the
 * avatar next to the name and date, then the text across the bottom — which
 * is a grid, so comment-text is dissolved to let its children take part in
 * one.
 */
.gp-reviews .comment_container {
	display: grid;
	grid-template-columns: 44px minmax(0, 1fr);
	grid-template-areas:
		"stars stars"
		"avatar meta"
		"body   body";
	gap: 4px 8px;
	align-items: center;
}

.gp-reviews .comment-text { display: contents; }

.gp-reviews .comment_container > .avatar {
	grid-area: avatar;
	background: rgba(5, 122, 7, 0.1);
	inline-size: 44px;
	block-size: 44px;
	border-radius: 50%;
	object-fit: cover;
}

.gp-reviews .star-rating { grid-area: stars; margin-block-end: 8px; }
.gp-reviews .meta { grid-area: meta; }
.gp-reviews .description { grid-area: body; margin-block-start: 12px; }

.gp-reviews .description p { margin: 0; }

/*
 * Author, verification and date arrive as one paragraph of inline elements.
 * The live entry puts the name on its own line with the date under it, so the
 * date is given the full width and the dash that joined them is dropped.
 */
.gp-reviews .meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	margin: 0;
	font-size: var(--wp--preset--font-size--base);
}

.gp-reviews .woocommerce-review__author { font-weight: 700; }

.gp-reviews .woocommerce-review__dash { display: none; }

.gp-reviews .woocommerce-review__verified {
	padding: 2px 8px;
	border-radius: 999px;
	background: rgba(5, 122, 7, 0.1);
	color: var(--wp--preset--color--highlight-green);
	font-size: 12px;
	font-style: normal;
}

.gp-reviews .woocommerce-review__published-date {
	flex-basis: 100%;
	font-size: 14px;
	color: rgba(0, 0, 0, 0.6);
}

/* ---------- the form ---------- */

.gp-reviews .comment-respond { margin-block-start: var(--wp--preset--spacing--60); }

.gp-reviews .comment-reply-title {
	display: block;
	margin-block-end: var(--wp--preset--spacing--40);
	font-size: 20px;
	font-weight: 600;
	color: var(--wp--preset--color--ink-heading);
}

/* Label above field rather than beside it: the labels are different lengths,
   so inline they leave the inputs on a ragged left edge. The star rating's
   own labels are excluded — they are the control, not a caption for it, and
   gp/review-modal sizes them. */
.gp-reviews .comment-form label:not(.gp-stars__star) {
	display: block;
	margin-block-end: 6px;
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
}

.gp-reviews .comment-form-cookies-consent label {
	display: inline;
	font-weight: 400;
}

.gp-reviews input[type="text"],
.gp-reviews input[type="email"],
.gp-reviews textarea,
.gp-reviews .comment-form-rating select {
	box-sizing: border-box;
	inline-size: 100%;
	max-inline-size: 540px;
	padding: 10px 12px;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 8px;
	background: var(--wp--preset--color--surface-alt);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--base);
}

.gp-reviews input[type="submit"],
.gp-reviews .submit {
	box-sizing: border-box;
	min-block-size: 44px;
	padding: 0 20px;
	border: 2px solid var(--wp--preset--color--brand-green);
	border-radius: 8px;
	background: var(--wp--preset--color--brand-green);
	color: var(--wp--preset--color--surface);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--base);
	cursor: pointer;
}

.gp-reviews input[type="submit"]:hover,
.gp-reviews .submit:hover {
	border-color: var(--wp--preset--color--highlight-green);
	background: var(--wp--preset--color--highlight-green);
}

/* ---------- recently viewed ---------- */

/* On the product page the row is a section like any other, so it gets the
   same heading treatment the shop rows use. */
.gp-recent__title {
	font-size: 22px;
	font-weight: 600;
	color: #000;
}


/* ================================================= matching the live page -- */

/*
 * The live product page frames almost nothing: the cover sits on the page
 * without a card around it, the tabs are a rule and three labels, and the
 * reviews run straight down the column. Only the assistance list is a panel,
 * and gp/product-assistance already draws it. What is left for this file is
 * the geometry the blocks cannot know — how wide the cover column is, and how
 * the sections below the fold are spaced.
 */

/* ---------- gallery ---------- */

/* The cover fills its column. The block already draws the slide at 3/4, so
   the column's width is the only thing deciding how large the book is, and a
   cap here would only waste the space a high-resolution cover can use. */
.gp-product__media .gp-gallery {
	position: sticky;
	inset-block-start: 24px;
}

.gp-product__media .gp-gallery__image {
	border-radius: 4px;
	object-fit: contain;
}

/* ---------- see more ---------- */

/* The live page truncates the description and offers a way into the full text
   rather than a second copy of it; the link goes to the tabs below. */
.gp-product__more {
	margin-block: 4px 0;
	font-size: var(--wp--preset--font-size--base);
}

.gp-product__more a {
	color: #000;
	text-decoration: none;
	border-block-end: 1px solid currentColor;
	padding-block-end: 2px;
}

/* ---------- sections below the fold ---------- */

/* 18px/600 is the live figure for the related-products heading — a label over
   the row, not a display heading. */
.gp-product__section-title {
	margin-block: var(--wp--preset--spacing--70) var(--wp--preset--spacing--40);
	font-size: 18px;
	font-weight: 600;
	line-height: 1.1;
	color: #000;
}

@media (max-width: 900px) {
	/* Stacked, a sticky cover would sit over the copy it belongs to. */
	.gp-product__media .gp-gallery { position: static; }
	.gp-product__media { flex-basis: 100% !important; }

	/*
	 * The wrapper has to be told to wrap, not only the column to fill the
	 * row. Core pins `flex-wrap: nowrap !important` on every columns block
	 * from 782px up, so between there and here the first column took the
	 * whole width and the second was left at zero — its contents spilled
	 * out of the page instead of dropping to a line of their own. Below
	 * 782px core wraps them itself, which is why only this band broke.
	 */
	.gp-product { flex-wrap: wrap !important; }
}


/* ---------- the buy row, narrow ---------- */

/*
 * The break into two lines is arranged above and holds at every width. What is
 * left here is the second line itself: 210px buttons do not fit side by side on
 * a phone, so they give up their fixed width and share what there is.
 */
@media (max-width: 780px) {
	/* A basis wide enough that the pair cannot fit beside the stepper: that is
	   what puts them on their own line, and they share it evenly from there. */
	.gp-product__buy-row .wc-block-components-product-button,
	.gp-product__buy-row .gp-buy-now { flex: 1 1 120px; min-inline-size: 0; }

	/* Three classes deep, because WooCommerce's own button width lands later
	   in the cascade than this file does. */
	.gp-product__buy-row .wc-block-components-product-button .wc-block-components-product-button__button {
		min-inline-size: 0;
		inline-size: 100%;
		padding: 0 12px;
	}

	.gp-product__buy-row .gp-buy-now__form,
	.gp-product__buy-row .gp-buy-now__button { inline-size: 100%; }
}

/*
 * The related-products row is a rail now — a horizontal scroll-snap track,
 * matching the live page's Swiper carousel — so its column width comes from
 * rail.css (see .gp-product-rail there), the same file every homepage row and
 * the cart's featured collection already use. Nothing about column count is
 * stated here any more.
 */

/* A product with nothing related to it renders no collection element at all —
   WooCommerce drops the whole block rather than emitting an empty grid — which
   would otherwise leave this heading standing over nothing. */
.gp-product__section-title:not(:has(+ .wp-block-woocommerce-product-collection)) {
	display: none;
}

/* ---------- "See more" jump ---------- */

/*
 * The "See more" link is an in-page jump from the summary down to the tabs.
 * Landing there instantly is disorienting: the panel it arrives at looks
 * nothing like what was on screen a moment before, so there is no sense of
 * having travelled. Animating the jump keeps the reader oriented.
 *
 * This file loads on product pages only, so the smooth scroll is scoped to
 * the page that has the link. The two dropdowns that step through a list with
 * the arrow keys ask for `behavior: 'instant'` explicitly, so they are not
 * dragged into this.
 */
@media (prefers-reduced-motion: no-preference) {
	html { scroll-behavior: smooth; }
}

/* Land the section a little clear of the top rather than flush against it,
   so the heading reads as the start of something. */
.gp-product__detail { scroll-margin-block-start: 24px; }
