/* ============================================================
   Dot Experience — WooCommerce Shop Archive + Single Product
   ============================================================
   Restyles the shop/category archive product grid
   (templates/archive-product.html), the single-product gallery +
   buy box + related-products grid (templates/single-product.html,
   patterns/related-products.php), and the two companion-plugin
   notice shortcodes ([wcreq_addon_prompt], [qdw_discount_notice])
   using this theme's design tokens. Only loaded on the shop
   archive, product category/tag archives, and single-product pages
   — see dot_experience_styles() in functions.php.

   Per this theme's "restyle via class-name targeting" convention:
   the .product-card/.product-card__*, .product-buy-box*, and
   .product-gallery-frame hooks are className attributes already
   added directly to the relevant blocks in the template/pattern
   markup; this file is the applied layer on top, same relationship
   base.css has to tokens.css.
   ============================================================ */

/* ============================================================
   0. Category-grouped product grids (Tickets page / category archives)
   ============================================================
   As of the Tickets/Shop split (see docs/DECISION-LOG.md), Tickets
   is a real WordPress Page (templates/page-tickets.html) rather than
   a product-category archive — it hosts the ticket-cards block, the
   Donation callout (§0b below), and a Gift Shop product grid, in that
   order. templates/archive-product.html is now the distinct Shop
   landing page (heroes + editorial category-spread sections, styled
   by their own block stylesheets, not this file) and
   templates/taxonomy-product_cat.html is a plain generic category
   archive for any /product-category/{slug}/ visited directly. This file's
   `.product-card`/`.product-card-grid` rules remain the shared
   restyle layer for every `woocommerce/product-collection` grid
   across all three surfaces, using multiple `product-collection`
   blocks instead of one flat query loop — one filtered by category
   (product_cat taxQuery), one using a single hand-picked product ID
   (the Donation card). Product Collection always applies WooCommerce's
   own catalog-visibility exclusion internally regardless of which
   query type is used (confirmed by reading this WC version's
   ProductCollection/QueryBuilder::get_product_visibility_query(),
   which unconditionally merges an exclude-from-catalog tax_query
   clause into every collection query) — Hidden/staff-mediated
   products can't appear here without a custom query bypassing that,
   which this template does not do.

   Product Collection's actual flex/grid container is the inner
   `<ul class="wc-block-product-template">` the block renders one
   level below the `.wp-block-woocommerce-product-collection` div
   this theme's className attribute lands on (confirmed live via
   computed styles: that `<ul>` carries `is-flex-container columns-N`
   and a real `display:flex`, which is what actually sizes each
   product `<li>` — overriding `display` on the outer wrapper alone
   left the inner `<ul>` still flexing, capping the featured card to
   a single flex-item's width instead of the full shell). Both rules
   below target that inner `<ul>` via the outer wrapper's className,
   with !important to reliably win over Woo's own same-specificity
   class selector regardless of DOM/enqueue order — the same problem
   this theme's .dot-footer and .dot-utility-bar icon-button rules
   already solve the same way (see base.css), not a new pattern.
   ============================================================ */

/* The Product Collection block's own displayLayout (columns:4) also lays a
   4-column grid onto THIS outer wrapper, which drops the real product <ul>
   into a single ~620px track and leaves three empty tracks beside it — so
   the grid rendered at roughly half the shell width and squeezed every
   card (and its price/button) into ~140px regardless of viewport. Reset
   the wrapper to a plain block box so the inner <ul> below (which is the
   actual grid) fills the shell and its four columns size evenly. The
   (0,2,0) selector wins over WordPress's generated layout container rule
   (0,1,0) without !important. Scoped to .product-card-grid so the
   single-card collections (.dot-single-card, one column) are untouched.

   This rule was silently never applying in production. The §0 doc
   comment above used to spell out the taxonomy archive route with a
   trailing wildcard segment immediately followed by a closing slash;
   written literally, those two punctuation marks in sequence are CSS's
   own comment-terminator token, and comments aren't nesting-aware or
   context-sensitive about it. That closed the §0 comment dozens of
   lines early, so everything after it (prose, the next doc comment
   above, and this rule's own selector) was consumed by the parser as
   one long invalid selector and dropped along with the declaration
   block that followed it, which is exactly why the reset never took
   effect and the "outer wrapper squeezed to ~140px" symptom this
   comment describes reached production on both the taxonomy archive
   and the Tickets Gift Shop section (same shared CSS). Fixed by
   rewording the §0 sentence to use a {slug} placeholder instead of a
   bare wildcard-plus-slash. Worth a second pass over this file (and any
   other theme CSS) for the same hazard before writing new comments that
   reference literal wildcard paths. */
.wp-block-woocommerce-product-collection.product-card-grid {
	display: block;
}

.wp-block-woocommerce-product-collection.product-card-grid .wc-block-product-template {
	display: grid !important;
	grid-template-columns: 1fr;
	gap: 1.25rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

@media (min-width: 768px) {
	.wp-block-woocommerce-product-collection.product-card-grid .wc-block-product-template {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 1024px) {
	.wp-block-woocommerce-product-collection.product-card-grid .wc-block-product-template {
		grid-template-columns: repeat(4, 1fr);
	}
}

/* width:100% is load-bearing: without it each <li> collapses to ~50px
   (its content min) inside the 1fr track instead of filling it, and the
   card overflows a tiny li. WooCommerce's own woocommerce-layout.css sets
   an li width at the same specificity and later enqueue order, so plain
   width:100% loses the tie — hence !important, the same fight (and fix)
   this file's `.wc-block-product-template { display:grid !important }`
   rule above already documents. Once the li fills its track, the card's
   own `flex:1 1 auto` (below) stretches it to the full column width and
   row height so a row of cards stays even. */
.wp-block-woocommerce-product-collection.product-card-grid .wc-block-product-template > li {
	margin: 0;
	list-style: none;
	display: flex;
	width: 100% !important;
}

/* Single-card contexts (the oversized featured tile, the standalone
   Donation card) only ever render one child — reset Product
   Collection's own flex wrapper to a plain block box so each
   card component's own width rules (below) are what actually size
   it, not Woo's multi-column flex math. */
.wp-block-woocommerce-product-collection.dot-single-card .wc-block-product-template {
	display: block !important;
	list-style: none;
	margin: 0;
	padding: 0;
}

.wp-block-woocommerce-product-collection.dot-single-card .wc-block-product-template > li {
	margin: 0;
	list-style: none;
}

/* ============================================================
   0b. Donation callout — "Pay It Forward" spotlight
   ============================================================
   Tickets page (templates/page-tickets.html), directly under the
   ticket-cards block. This used to be a dead, unused
   ".featured-product-card" variant (an oversized-but-otherwise-
   generic product-card clone that no markup ever referenced) plus
   the live Donation card, which rendered with the exact same
   .product-card/.product-card__* markup as every plain Gift Shop
   grid item, capped to max-width:22rem (the removed
   .dot-standalone-card rule) — reading as an afterthought next to
   ticket-cards' deliberately asymmetric layout.

   This is a purpose-built replacement, not a revival of the old
   featured-product-card: a donation reads differently than a ticket
   or a t-shirt, so it does not borrow ticket-cards' ink-inverted
   "featured purchase" panel (that treatment is already spoken for,
   directly above this block, for General Admission) or a plain
   product-card's shelf-item framing. Instead it's a full-width,
   quiet-surface band — a heavier 2px hairline border (this theme's
   monochrome palette has no separate accent hue to reach for, so
   visual weight comes from border weight, scale, and layout, not
   color), a circular decorative Braille-cell medallion (the same
   "single raised cell" motif blocks/hero-ticket-a uses for its ticket
   stub, reused here rather than invented fresh), a large mission-
   led heading + blurb (static, editorial copy — not the raw product
   title), and a dashed rule separating that mission copy from the
   live bit: the product's real title/price/Add to cart button,
   resolved from product #154 by the woocommerce/product-collection
   block in the template (same block, same dot-single-card grid-reset
   rules below — only the inner card markup/classNames changed).
   Deliberately has no product-image block: a donation is conceptual,
   not a photographed item, and product #154 has no real photo set —
   the medallion stands in for it rather than rendering a generic
   WooCommerce placeholder photo.
   ============================================================ */
.dot-donation-callout {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.5rem;
	background: var(--surface);
	border: 2px solid var(--ink);
	border-radius: var(--r-xl);
	padding: clamp(1.75rem, 3vw, 2.75rem);
}

@media (min-width: 768px) {
	.dot-donation-callout {
		flex-direction: row;
		align-items: flex-start;
		gap: 2.25rem;
	}
}

.dot-donation-callout__mark {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	inline-size: 4rem;
	block-size: 4rem;
	border-radius: 9999px;
	border: 1px solid var(--line);
}

/* Same 2-col x 3-row Braille cell device as blocks/hero-ticket-a's
   .dot-braille-cell — duplicated (not shared) since that class lives
   in a block stylesheet only loaded when that block renders, and
   this page does not use blocks/hero-ticket-a. Small enough that a
   shared abstraction isn't worth the indirection. */
.dot-donation-callout__braille {
	display: grid;
	grid-template-columns: repeat(2, 0.55rem);
	gap: 0.32rem;
}

.dot-donation-callout__braille i {
	inline-size: 0.55rem;
	block-size: 0.55rem;
	border-radius: 9999px;
}

.dot-donation-callout__braille i.is-on {
	background: var(--ink);
}

.dot-donation-callout__braille i.is-off {
	background: transparent;
	box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 22%, transparent);
}

.dot-donation-callout__body {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	min-width: 0;
}

.dot-donation-callout__eyebrow {
	margin: 0;
}

.dot-donation-callout__heading {
	margin: 0;
	font-size: var(--step-2);
	line-height: 1.1;
}

.dot-donation-callout__blurb {
	margin: 0;
	max-width: 46ch;
	font-size: var(--step-0);
	color: var(--muted);
	line-height: 1.5;
}

/* The live bit: product title/price/button, separated from the
   mission copy above by a dashed rule — a quiet nod to a receipt or
   pledge-slip stub, distinct from ticket-cards' perforated-notch
   ticket-stub device. */
.dot-donation-callout__product {
	margin-top: 0.4rem;
	padding-top: 1.1rem;
	border-top: 1px dashed var(--line);
	width: 100%;
}

.dot-donation-callout__meta {
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
}

.dot-donation-callout__price-col {
	gap: 0.15rem;
}

.dot-donation-callout__label {
	font-size: 0.8rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--muted);
}

.dot-donation-callout__price .wc-block-components-product-price,
.dot-donation-callout__price .price {
	font-size: 1.5rem;
	font-weight: 800;
	color: var(--ink);
}

.dot-donation-callout__button .add_to_cart_button,
.dot-donation-callout__button .button,
.dot-donation-callout__button .wc-block-components-button {
	background: var(--ink);
	color: var(--bg);
	border-color: var(--ink);
}

/* ============================================================
   1. Product card — shop archive + related-products grid
   ============================================================
   Deliberately does NOT use core Post Template's own "grid" layout
   support (would fight this rule on specificity — core emits a
   4x-repeated class selector for its own grid-template-columns).
   templates/archive-product.html and patterns/related-products.php
   both set the Post Template block's layout to "flow" instead and
   apply this class directly, so this is the only grid rule in play.

   Breakpoints: 768px/1024px only, per this theme's fixed 3-tier
   (mobile/md/lg) responsive convention — no sm/xl tiers.
   ============================================================ */
.product-card-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: 1.25rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

@media (min-width: 768px) {
	.product-card-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 1024px) {
	.product-card-grid {
		grid-template-columns: repeat(4, 1fr);
	}
}

.product-card-grid > li {
	margin: 0;
	list-style: none;
	display: flex;
}

.product-card {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r-lg);
	padding: 1.1rem;
}

.product-card__image {
	margin-bottom: 1rem;
}

.product-card__image img {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	border-radius: var(--r-md);
	border: 1px solid var(--line);
}

.product-card__title {
	font-size: 1.1rem;
	font-weight: 800;
	line-height: 1.3;
	margin: 0 0 0.75rem;
}

/* axe-core "target-size": as plain inline text (no padding/min-height),
   this link's clickable box was only its line-box — ~1.1rem font-size ×
   1.3 line-height ≈ 22.9px tall, under the 24px WCAG minimum. `display:
   inline-block` (same technique already used for `.dot-classic-menu__
   list a` above) makes padding actually contribute to the hit area
   instead of being visually-only; the padding is block-start/end only
   (not per wrapped line) so a 2-line title only gains it once, at the
   very top and bottom of the whole title, not between the two lines.
   0.15rem top+bottom (≈2.4px each) brings the box to ~27.7px — clears
   24px with a safety margin, without the 44px utility-bar/nav-toggle
   convention's bulk, which would visually overpower this compact card
   title. */
.product-card__title a {
	display: inline-block;
	padding-block: 0.15rem;
	color: var(--ink);
	text-decoration: none;
}

.product-card__title a:hover {
	text-decoration: underline;
}

/* Price and the action button each get their own row (price above,
   button below) instead of sharing one — a full-width button reads clean
   in a dense 4-up grid and keeps a row of cards from going ragged across
   the variable button labels ("Add to cart" / "Select options" / "Read
   more" / "1 in cart"). The whole footer is pinned to the bottom of the
   card (margin-top:auto) so those button rows line up across otherwise
   uneven cards. The (0,2,0) selector wins over WordPress's own generated
   flex-layout container rule (0,1,0) without needing !important. */
.product-card .product-card__footer {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 0.7rem;
	margin-top: auto;
}

.product-card__price .wc-block-components-product-price,
.product-card__price .price {
	font-size: 1.05rem;
	font-weight: 700;
	color: var(--ink);
}

/* WooCommerce Blocks' own product-button-style.css sets this wrapper
   (`.wc-block-components-product-button`, the block's own class, present
   alongside our `.product-card__button` className) to `display:flex;
   flex-direction:column; gap:12px` — see
   wp-content/plugins/woocommerce/assets/client/blocks/woocommerce/
   product-button-style.css. That column layout exists to stack the Add to
   Cart button above the block's own conditionally-revealed "View cart"
   link (a `<span hidden data-wp-bind--hidden="!state.displayViewCart">`
   sibling — see ProductButton::get_view_cart_html()), which is exactly
   the "button grows tall and fat" symptom this task was asked to fix: once
   an item is added, that span un-hides and the 12px gap + stacked link
   add real height/width to the card footer.

   Now that parts/header.html's Mini-Cart block has
   `addToCartBehaviour:"open_drawer"` (2026-07-13 fix), the drawer opens
   automatically on add-to-cart, making this inline "View cart" text
   redundant on grid cards — so it's hidden outright rather than merely
   restyled, and the wrapper is reset to a plain block box the same width
   as the button itself, keeping the card's footprint visually identical
   before and after the add-to-cart state change. */
.product-card__button {
	display: block;
	width: 100%;
}

.product-card__button .added_to_cart.wc_forward {
	display: none !important;
}

/* Fill the card width so every card's CTA is the same size regardless of
   its label length ("Add to cart" / "Read more" / "1 in cart") — that's
   what keeps a row of cards from going ragged. base.css already centers
   the label. !important for the same reason the grid/li rules above use
   it: WooCommerce's own button CSS otherwise wins this same-specificity
   tie and sizes the button to its content. */
.product-card__button .wp-block-button__link,
.product-card__button .wc-block-components-product-button__button,
.product-card__button .add_to_cart_button,
.product-card__button .button {
	width: 100% !important;
}

/* Keep the label on one line. base.css already sets white-space:nowrap
   on these same classes (its ".button, .wp-element-button, ..." group,
   specificity (0,1,0) per selector) specifically so buttons stay pill-
   shaped, but WooCommerce's own product-button-style.css ships
   `.wp-block-button.wc-block-components-product-button
   .wc-block-components-product-button__button { white-space: normal }`
   at (0,3,0), a higher-specificity win regardless of enqueue order,
   same class of problem the width rule above already documents. Left
   unfixed, a 3-word label ("Add to cart") wraps across multiple lines
   inside the fully-round (9999px radius) button, ballooning it into a
   tall blob instead of a pill, visibly different from the single-line
   "Read more"/"Select options" buttons beside it in the same grid row,
   which is the "messed up" card-button look this scoped fix corrects. */
.product-card__button .wc-block-components-product-button__button,
.product-card__button .add_to_cart_button,
.product-card__button .button {
	white-space: nowrap !important;
}

/* ============================================================
   2. Single product — gallery frame
   ============================================================
   Replaces the default WooCommerce gallery's lack of any frame with
   the standard card radius + hairline border (brief: gallery main
   image gets --r-lg + border). Targets the classic gallery's own
   stable class names (product-image-gallery block server-renders
   the classic woocommerce-product-gallery markup) rather than
   duplicating it.
   ============================================================ */
.product-gallery-frame .woocommerce-product-gallery__wrapper {
	overflow: hidden;
	border-radius: var(--r-lg);
	border: 1px solid var(--line);
}

.product-gallery-frame .woocommerce-product-gallery__image img {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: cover;
}

/* Thumbnail rail, only present once the flexslider/zoom script has
   enhanced the gallery client-side (progressive enhancement — with
   JS disabled there's no thumbnail rail and the rules below are
   simply inert). */
.product-gallery-frame .flex-control-thumbs {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0.75rem 0 0;
	padding: 0;
	list-style: none;
}

.product-gallery-frame .flex-control-thumbs li {
	margin: 0;
}

.product-gallery-frame .flex-control-thumbs img {
	display: block;
	width: 4rem;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	border-radius: var(--r-sm);
	border: 1px solid var(--line);
	cursor: pointer;
}

/* ============================================================
   3. Single product — buy box
   ============================================================ */
.product-buy-box__price .wc-block-components-product-price,
.product-buy-box__price .price {
	font-size: 1.5rem;
	font-weight: 800;
	color: var(--ink);
}

/* ---- 3a. Per-variation price (variable products, e.g. FooEvents
   Bookings' Age Group selector) ----
   Confirmed live (Factory Tours, a Bookings-enabled variable
   product): once a variation is selected, WooCommerce core renders a
   SECOND, separate price element — .woocommerce-variation-price .price
   inside .single_variation_wrap, a sibling of the top .product-buy-box__price
   range block, not a descendant of it. Unlike that top price, this one
   ships with NO type treatment (18px/400-weight body text, confirmed
   via computed styles) and sits in equal ~28px whitespace above and
   below (WooCommerce's own twenty-twenty-three.css:
   `.single_variation_wrap { margin-top: var(--wp--style--block-gap) }`,
   plus the same block-gap value again as .woocommerce-variation's own
   margin-bottom) — exactly the "lost / disconnected from everything
   else" complaint: no visual weight tying it to "this is a price," and
   no visual attachment to either neighbour.

   Fix: give it the same bold price treatment as the top range price
   (so picking a variation reads as a real, visible price readout, not
   plain text), then re-balance the whitespace so it reads as DIRECT
   feedback from the Age Group control immediately above (tight gap)
   rather than a floating paragraph — the larger, clearer break moves
   to below it, ahead of the Booking-details/add-to-cart step, which is
   the one that actually deserves a section boundary.

   The two margin overrides need !important: both properties are also
   set by core WooCommerce stylesheets that are NOT dequeued on the
   product page (only dequeued on the classic cart/checkout shortcode
   surfaces, per woocommerce-cart-checkout.css's header) via
   higher-specificity compound selectors —
   `.woocommerce div.product .single_variation_wrap` (twenty-twenty-
   three.css) and `.woocommerce .single_variation_wrap
   .woocommerce-variation` (woocommerce-blocktheme.css), both (0,3,*) —
   confirmed live via document.styleSheets that a plain
   `.product-buy-box .single_variation_wrap` (0,2,0) rule loses to
   them. Same documented WC-specificity-fight convention already used
   in base.css/gravity-forms.css/woocommerce-cart-checkout.css. */
.product-buy-box .woocommerce-variation-price .price {
	font-size: 1.5rem;
	font-weight: 800;
	color: var(--ink);
}

.product-buy-box .single_variation_wrap {
	margin-top: var(--wp--preset--spacing--30) !important;
}

.product-buy-box .woocommerce-variation {
	margin-bottom: var(--wp--preset--spacing--40) !important;
}

/* ---- 3b. Add-to-cart row vs. express-checkout (Apple/Google Pay,
   Link) button spacing ----
   Confirmed live: woocommerce-gateway-stripe renders its express-
   checkout buttons (#wc-stripe-express-checkout-element) as a SIBLING
   of form.cart / form.variations_form.cart — both direct children of
   the add-to-cart-form block wrapper (.wp-block-add-to-cart-form),
   never inside the form itself. Stripe's own JS sets an inline
   `margin-top: 1em` on that div, which (being an inline style) can't
   be overridden by an external stylesheet rule targeting the same
   longhand property without !important — so the fix works the OTHER
   side of the gap instead: the form's own margin-bottom, which
   collapses with Stripe's inline top margin (adjacent block margins
   take the larger of the two, not the sum) up to whichever is bigger.
   A hairline + small padding-top on the Stripe wrapper itself (neither
   touched by its inline style) then reinforces the boundary — the same
   "distinct group" device this theme already uses for the checkout's
   field-group breaks (see woocommerce-cart-checkout.css). Together
   these turn the near-zero-gap "one cramped cluster" the client
   flagged into two clearly separate groups: the real add-to-cart
   action, and the express-checkout alternatives below it. */
.product-buy-box form.cart {
	margin-bottom: var(--wp--preset--spacing--60);
}

.product-buy-box #wc-stripe-express-checkout-element {
	padding-top: var(--wp--preset--spacing--40);
	border-top: 1px solid var(--line);
}

/* ---- 3c. Unified select styling (Age Group / attribute selects +
   FooEvents Bookings' Select Date / Select Slot) ----
   Client-reported (screenshot): the WooCommerce variation-attribute
   select (Age Group, `table.variations select`, WC's own generic
   markup — no class, not wrapped in `.form-row`) renders as a small,
   plain, default-browser-chrome control, while FooEvents Bookings'
   Select Date/Select Slot selects look "designed" next to it (rounded,
   full width) — reading as two different form-control styles on the
   same page.

   WIDTH — confirmed live the Age Group select's `width: 100% !important`
   below was inert on its own: `.woocommerce table.variations{display:block}`
   (woocommerce-blocktheme.css) turns the table into a block box while its
   `<tr>`/`<th class="label">`/`<td class="value">` children keep default
   table-row/table-cell rendering, so they auto-size to CONTENT inside an
   anonymous table box rather than filling the real row width (confirmed:
   th.label ~112px, td.value ~191px, leaving ~400px of the 700px row
   unused) — a select at 100% of a ~191px shrink-wrapped cell is still a
   narrow, "native-looking" control. FooEvents' Select Date/Slot don't have
   this problem: their markup stacks label above field (`.form-row`), no
   side-by-side cell to shrink-wrap. Converting the row to flex (below)
   makes th.label size to its own content and td.value consume the rest of
   the row, so the select's existing width:100% finally has real width to
   fill — the two field families still don't share identical markup
   (label-beside vs. label-above), so pixel-for-pixel identical widths
   aren't achievable without restructuring the classic variation-table
   layout entirely (out of scope for a styling-consistency fix), but this
   gets Age Group out of "small native box" territory and onto the same
   full-width-of-its-row behavior Select Date/Slot already have. Also
   generalizes correctly to any product with multiple attributes (Size,
   Color, etc.) — each becomes its own label+full-width-select row. */
.product-buy-box table.variations tr {
	display: flex !important;
	align-items: center;
	gap: 0.75rem;
	flex-wrap: wrap;
}

.product-buy-box table.variations tr th.label {
	flex: 0 0 auto;
}

.product-buy-box table.variations tr td.value {
	flex: 1 1 240px;
	min-width: 0;
}

.product-buy-box table.variations select,
.product-buy-box .woocommerce-variation-add-to-cart select {
	display: block !important;
	width: 100% !important;
	min-height: 48px !important;
	height: auto !important;
	padding: 0.7rem 2.5rem 0.7rem 0.9rem !important;
	margin: 0 !important;
	font-family: inherit !important;
	font-size: 1rem !important;
	line-height: 1.4 !important;
	color: var(--ink) !important;
	background-color: var(--bg) !important;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%230b0b0b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 1rem center;
	background-size: 0.75rem;
	border: 1px solid var(--muted) !important;
	border-radius: var(--r-sm) !important;
	box-shadow: none;
	box-sizing: border-box;
	appearance: none;
	-webkit-appearance: none;
	transition: border-color var(--motion-med) var(--ease),
		box-shadow var(--motion-med) var(--ease);
}

[data-theme="dark"] .product-buy-box table.variations select,
[data-theme="dark"] .product-buy-box .woocommerce-variation-add-to-cart select {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23f4f2ec' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
}

.product-buy-box table.variations select:hover,
.product-buy-box .woocommerce-variation-add-to-cart select:hover {
	border-color: var(--ink);
}

.product-buy-box table.variations select:focus,
.product-buy-box .woocommerce-variation-add-to-cart select:focus {
	border-color: var(--accent);
	box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 16%, transparent);
	outline: none;
}

.product-buy-box table.variations select:focus-visible,
.product-buy-box .woocommerce-variation-add-to-cart select:focus-visible {
	outline: 3px solid var(--focus);
	outline-offset: 2px;
}

/* ---- 3d. Age Group label ↔ select spacing ("floating away") ----
   Client-reported (screenshot): "Age Group" reads detached from its own
   select, floating well above it. Confirmed live (Factory Tours/General
   Admission, both variable): at this buy box's actual column width
   (~330px), 3c's `tr { display:flex; flex-wrap:wrap }` always wraps
   th.label onto its own line above td.value — th (auto width) + the
   0.75rem gap + td's 240px min flex-basis simply don't fit — which is
   the intended "label above full-width field" footing 3c's own doc
   comment already puts Age Group on, matching FooEvents Bookings' Select
   Date/Slot rows. The stack itself isn't the bug. The GAP is: WooCommerce
   core's woocommerce-blocktheme.css sets `.woocommerce table.variations
   tr td, .woocommerce table.variations tr th { padding-bottom:
   var(--wp--style--block-gap) }` — confirmed live via computed styles,
   28px on th.label — real space added below the label, on top of the
   tr's own 0.75rem (12px) flex gap between th and td. The two stack to
   ~40px of dead air between "Age Group" and its select. Zeroing th's
   share leaves just the flex gap, the same label-to-field distance used
   elsewhere in this row. !important for the same defensive-against-
   enqueue-order reasoning as every other override in this section (this
   selector's specificity already wins over woocommerce-blocktheme.css's
   without it, but this follows the established convention rather than
   relying on that alone). */
.product-buy-box table.variations tr th.label {
	padding-bottom: 0 !important;
}

/* ---- 3e. "Clear" (.reset_variations) link — visual definition + spacing ----
   Client-reported (screenshot): the Clear link renders as bare, unstyled
   text sitting close beneath the select, easy to miss. `.reset_variations`
   is WooCommerce core's own stable class for this link (confirmed live,
   both products) — plain markup, no FooEvents involvement. WooCommerce's
   own JS (add-to-cart-variation.js) only ever toggles this link's inline
   `visibility` style, never `display`, so styling `display` here doesn't
   fight that behavior. The select above it is already a full-width block
   (3c), so this link already falls onto its own line below it in normal
   flow — only spacing and real visual weight were missing. Given the
   same quiet outline-pill secondary-action treatment already used
   sitewide for this exact kind of action — .fooevents-add-more-bookings
   (woocommerce-mini-cart.css) and the cart/checkout "Apply coupon" button
   (woocommerce-cart-checkout.css) — rather than inventing a new style:
   resting hairline pill, fills solid ink on hover/focus. */
.product-buy-box .reset_variations {
	display: inline-flex;
	align-items: center;
	width: max-content;
	margin-top: 0.6rem;
	padding: 0.35rem 0.9rem;
	border-radius: 9999px;
	box-shadow: inset 0 0 0 1px var(--line);
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--ink);
	text-decoration: none;
	transition: background-color var(--motion-med) var(--ease),
		color var(--motion-med) var(--ease);
}

.product-buy-box .reset_variations:hover,
.product-buy-box .reset_variations:focus {
	background-color: var(--ink);
	color: var(--bg);
}

.product-buy-box .reset_variations:focus-visible {
	outline: 3px solid var(--focus);
	outline-offset: 2px;
}

/* ---- 3f. Quantity stepper — match the Age Group/Select Date/Slot
   selects' border, radius, height, and focus treatment ----
   Client-reported: "the quantity field also needs to be consistent with
   the styling of our other fields." Confirmed live (Factory Tours):
   `input[type=number].qty` renders with the browser's native double-inset
   border and square corners (computed: `border: 2px inset rgb(118, 118,
   118)`, `border-radius: 0`), sitting right next to the select controls
   3c already restyled — a visibly different form-control language on the
   same buy box. Doesn't need to match the select's WIDTH (it's a small
   numeric stepper, not a full-width field) — mirrors the cart page's own
   stepper instead (woocommerce-cart-checkout.css's
   `.woocommerce-cart-form .quantity input.qty`), which already solved
   this exact "native-looking number input next to styled controls"
   problem there; same border/radius/focus values, ~48px height to match
   3c's select `min-height` exactly rather than the cart stepper's 44px. */
.product-buy-box .quantity input.qty {
	width: 4.5rem;
	min-height: 48px;
	padding: 0.5rem;
	text-align: center;
	font-size: 1rem;
	color: var(--ink);
	background: var(--bg);
	border: 1px solid var(--muted);
	border-radius: var(--r-sm);
	-moz-appearance: textfield;
}

.product-buy-box .quantity input.qty:focus {
	border-color: var(--accent);
	box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 16%, transparent);
	outline: none;
}

.product-buy-box .quantity input.qty:focus-visible {
	outline: 3px solid var(--focus);
	outline-offset: 2px;
}

.product-buy-box__excerpt {
	font-size: var(--step-0);
	color: var(--muted);
	line-height: 1.6;
}

.product-buy-box__meta {
	flex-wrap: wrap;
	gap: 0.5rem 1rem;
	margin-top: 1rem;
}

/* Font-size/color set directly on the SKU/post-terms elements themselves,
   not just the wrapping .product-buy-box__meta group — WordPress's own
   global styles (`:root :where(.wp-block-post-terms){...}`) set an
   explicit font-size/color directly on these same elements, and an
   inherited value from an ancestor never wins over an explicit rule on
   the element itself regardless of specificity. Confirmed via computed
   styles during verification: without this, "Category: …"/SKU text
   rendered at the global-styles size/color instead of this theme's
   muted/small meta treatment. */
.product-buy-box__meta,
.product-buy-box__meta .wp-block-post-terms,
.product-buy-box__meta .wc-block-components-product-sku {
	font-size: 0.85rem;
	color: var(--muted);
}

.product-buy-box__meta a {
	color: var(--muted);
	text-decoration: underline;
	text-underline-offset: 0.15em;
}

/* ============================================================
   4. Product Tabs block (acf/product-tabs, blocks/product-tabs/render.php)
   ============================================================
   This block ships with NO CSS anywhere in the theme — confirmed via
   repo-wide search before writing this — so it was rendering as bare
   browser-default <ul>/<button> chrome (no tab-strip look at all)
   directly under the newly restyled buy box: exactly the "visually
   orphaned" case this wave was asked to catch and fix. Restyled here
   via class-name targeting only (.dot-product-tabs*, set by
   render.php's get_block_wrapper_attributes() and static class
   strings) — the block's structural markup, ARIA wiring, and
   inc/product-tabs.php's keyboard-interaction script are untouched.
   Tab-strip/active-tab/panel treatment follows this theme's existing
   conventions: hairline underline for the resting strip, a 1.5px
   solid ink underline for the active tab (this theme's emphasis-
   border weight, matching .btn-primary/.btn-outline's border), and
   the standard --r-lg card radius + hairline border for the panel. */
.dot-product-tabs {
	margin-top: 2rem;
}

.dot-product-tabs__list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1.25rem;
	list-style: none;
	margin: 0 0 1.5rem;
	padding: 0;
	border-bottom: 1px solid var(--line);
}

.dot-product-tabs__tab-item {
	margin: 0;
}

.dot-product-tabs__tab {
	display: inline-flex;
	align-items: center;
	padding: 0.65rem 0.1rem;
	margin-bottom: -1px;
	background: transparent;
	border: none;
	border-bottom: 1.5px solid transparent;
	font-size: 0.95rem;
	font-weight: 700;
	color: var(--muted);
	cursor: pointer;
	transition:
		color var(--motion-med) var(--ease),
		border-color var(--motion-med) var(--ease);
}

.dot-product-tabs__tab:hover {
	color: var(--ink);
}

.dot-product-tabs__tab.is-active {
	color: var(--ink);
	border-bottom-color: var(--ink);
}

.dot-product-tabs__panel {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r-lg);
	padding: 1.5rem;
	font-size: var(--step-0);
	color: var(--ink);
	line-height: 1.6;
}

.dot-product-tabs__panel > *:first-child {
	margin-top: 0;
}

.dot-product-tabs__panel > *:last-child {
	margin-bottom: 0;
}

/* ============================================================
   4b. Event Details tab (FooEvents' own tab-content field)
   ============================================================
   Client-reported (screenshot): this tab renders as one undifferentiated
   wall of text — "what to expect" prose, a bulleted list, then a run of
   "Label: value" lines (Start time, Venue, Phone, Email, etc.) with no
   visual structure telling the two kinds of content apart. Confirmed
   live (Factory Tours + General Admission, both current FooEvents
   placeholder copy): the panel already carries
   `.woocommerce-Tabs-panel--woocommerce_events` — set by
   blocks/product-tabs/render.php from the WooCommerce tab `key`
   (`sanitize_html_class( $key )`), not a class added for this fix — so no
   PHP/JS change was needed to get a stable hook. Each trailing detail
   line is its own `<p><b>Label: </b>value</p>`, the `<b>` always the
   paragraph's first child with no other markup distinguishing it from
   the prose `<p>`s above (confirmed live) — this is FooEvents' own
   output, editable by staff, not a class this theme controls. The fix
   therefore targets that structural shape via `:has()` rather than a
   class name or a fixed set of expected labels, so it holds up regardless
   of which labels staff enter, how many, or whether they use `<b>` or
   `<strong>`. Browsers without `:has()` support just see plain (still
   legible) prose — a progressive-enhancement fallback, not a functional
   loss, appropriate given the fix can't rely on markup it doesn't
   control.

   Prose measure: this panel renders ~1200px wide on desktop (full width
   below the two-column gallery/buy-box, unlike the buy box itself) — far
   too long a line length for this theme's 18px body copy. Capped to a
   readable measure, same idea as .dot-donation-callout__blurb's
   max-width above.

   Detail rows: styled as quiet bordered "field" rows (background
   var(--placeholder-base), hairline border, --r-sm radius — this file's
   existing card/notice language, e.g. .qdw-discount-notice/
   .wcreq-addon-prompt below) with the bold label demoted to a small
   uppercase tag ahead of its value, so the block reads as structured data
   rather than more prose. The adjacent-sibling rule keeps the visual
   break (extra top margin) on only the first row of a run, whatever its
   length, rather than repeating it between every consecutive detail row.
   ============================================================ */
.woocommerce-Tabs-panel--woocommerce_events > * {
	max-width: 62ch;
}

.woocommerce-Tabs-panel--woocommerce_events p:is(:has(> b:first-child), :has(> strong:first-child)) {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: 0.5rem;
	row-gap: 0.15rem;
	margin: 1.75rem 0 0;
	padding: 0.65rem 1rem;
	background: var(--placeholder-base);
	border: 1px solid var(--line);
	border-radius: var(--r-sm);
	font-size: 0.95rem;
	font-weight: 600;
	color: var(--ink);
}

.woocommerce-Tabs-panel--woocommerce_events p:is(:has(> b:first-child), :has(> strong:first-child)) + p:is(:has(> b:first-child), :has(> strong:first-child)) {
	margin-top: 0.5rem;
}

.woocommerce-Tabs-panel--woocommerce_events p:is(:has(> b:first-child), :has(> strong:first-child)) > :is(b:first-child, strong:first-child) {
	flex: none;
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--muted);
}

/* ============================================================
   5. Companion-product / quantity-discount notices
   ============================================================
   [wcreq_addon_prompt] and [qdw_discount_notice] (rendered directly
   in templates/single-product.html) ship with no CSS of their own
   from either plugin — left unstyled they'd render as bare
   browser-default text sitting inside an otherwise fully restyled
   buy box. Restyled here via class-name targeting, same convention
   as woocommerce-myaccount.css; neither shortcode's PHP output/
   wiring is touched.
   ============================================================ */
.qdw-discount-notice {
	margin: 0.75rem 0 0;
	padding: 0.65rem 1rem;
	background: var(--placeholder-base);
	border: 1px solid var(--line);
	border-radius: var(--r-sm);
	font-size: 0.9rem;
	color: var(--ink);
}

.wcreq-addon-prompt {
	margin: 0.75rem 0 0;
	padding: 0.85rem 1rem;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r-md);
}

.wcreq-addon-prompt__name {
	font-weight: 700;
	color: var(--ink);
}

.wcreq-addon-prompt__price {
	color: var(--muted);
	font-size: 0.9rem;
}

.wcreq-addon-prompt__button {
	margin-top: 0.5rem;
}

/* ============================================================
   6. Related products heading spacing
   ============================================================
   .display-3 (base.css) supplies the size/weight/tracking; this
   only tightens the section's own top rhythm since it sits directly
   under the Product Tabs block above it.
   ============================================================ */
.wp-block-woocommerce-related-products .display-3 {
	margin-top: 2rem;
}
