/*
Theme Name: Infuse3D
Theme URI: https://www.infuse3d.co.za/
Author: Infuse3D
Author URI: https://www.infuse3d.co.za/
Description: Custom block theme for Infuse3D — personalised 3D printing. Design tokens live in theme.json.
Version: 0.3.40
Requires at least: 6.7
Tested up to: 7.0
Requires PHP: 8.1
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: infuse3d
Tags: block-theme, e-commerce, custom-colors, custom-menu, full-site-editing
*/

/* Design tokens are defined in theme.json — do not hard-code colours,
   sizes or spacing here. Use var(--wp--preset--*) if CSS is unavoidable.
   Exception: the filament-strip gradient below. Those are physical filament
   colours from the Claude Design homepage — brand asset, not palette. */

/* Print-layer texture: faint horizontal lines every 9px, evoking the layer
   lines of an FDM print. Dark variant for the hero, light for sections. */
.i3d-layers-dark {
	background-image: repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.045) 0 1px, transparent 1px 9px);
}

.i3d-layers-light {
	background-image: repeating-linear-gradient(0deg, rgba(30, 30, 30, 0.035) 0 1px, transparent 1px 9px);
}

/* Filament strip: section divider cut from the 15 stocked filament colours,
   in the same shade order as the "Pick your colour" section — neutrals light
   to dark, then around the wheel. 100/15 = 6.667% per segment.
   Hairline borders contain the White segment where the strip meets a white
   section; without them it reads as a gap rather than a spool. */
.i3d-filament {
	height: 14px;
	border-top: 1px solid rgba(30, 30, 30, 0.08);
	border-bottom: 1px solid rgba(30, 30, 30, 0.08);
	background: linear-gradient(90deg,
		#f5f5f2 0 6.67%,
		#c7c9cc 6.67% 13.33%,
		#4a4d52 13.33% 20%,
		#1b1b1d 20% 26.67%,
		#c4262e 26.67% 33.33%,
		#6b4429 33.33% 40%,
		#f26722 40% 46.67%,
		#c9a227 46.67% 53.33%,
		#f2c300 53.33% 60%,
		#2e9e4b 60% 66.67%,
		#8fd8b8 66.67% 73.33%,
		#2bb3a3 73.33% 80%,
		#1f6fd0 80% 86.67%,
		#6a2fa0 86.67% 93.33%,
		#e8619d 93.33% 100%);
}

/* Sticky translucent header.
   The blur is switched off below 600px — see the mobile overlay block further
   down. It is load-bearing, not decorative: a backdrop-filter here traps the
   fixed-position overlay menu inside this element. Do not reinstate it at
   mobile widths without reading that comment. */
.i3d-sticky-header {
	position: sticky;
	top: 0;
	z-index: 50;
	background: rgba(255, 255, 255, 0.94);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
	border-bottom: 1px solid var(--wp--preset--color--neutral-200);
}

/* Image placeholder panels in cards until product photography lands.
   Diagonal hatch per the corrected home design — reads as "slot", not "bug". */
.i3d-placeholder {
	background: repeating-linear-gradient(45deg, var(--wp--preset--color--neutral-100) 0 12px, var(--wp--preset--color--neutral-200) 12px 24px);
	min-height: 150px;
}

/* Photo in a category card: a square panel showing the whole shot.

   A fixed 200px band with object-fit:cover was cutting 31% off the square
   photos and 40% off the portrait one, which is why the school keyring lost
   its ends. Square + contain instead — the two 500x500 photos then fill the
   panel exactly with no letterbox at all, and the 652x762 one is the only
   image with side gaps, at roughly 7% a side.

   Those gaps are white because the photos are: every edge pixel sampled
   rgb(255,255,255), so the panel background disappears into the shot rather
   than framing it. A photo on a coloured ground would need this changed.

   The card needs overflow:hidden — the hatched spacers never showed the lack,
   being flat colour, but a photo squares off over the 16px radius without it. */
.i3d-cat-img {
	margin: 0;
}

/* The anchor must be block. WordPress wraps a linked image in an inline-block
   <a>, which shrink-wraps its content — so the img's width:100% resolved
   against the anchor rather than the card, and the image sized itself from its
   own aspect ratio at 200px tall and sat against the left edge. Measured at
   200px wide in a 288px card before this; 288px after. */
.i3d-cat-img a {
	display: block;
}

.i3d-cat-img img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1 / 1;
	object-fit: contain;
	background: var(--wp--preset--color--base);
}

/* Whole-card hover lift for linked cards. overflow:hidden so a card photo is
   clipped by the 16px radius rather than squaring off its top corners. */
.i3d-hover-card {
	overflow: hidden;
	transition: box-shadow 0.2s ease;
}

.i3d-hover-card:hover {
	box-shadow: var(--wp--preset--shadow--card);
}

/* Headings and lists inside the product description.

   Specifications, Material and care, and Please note live as headed sections
   within the description rather than in separate fields, so these headings do
   the structural work a separate box would otherwise have done. Without this
   they inherit heading sizes tuned for page titles and the section breaks are
   lost in a wall of prose. */
.woocommerce-Tabs-panel--description h2,
.woocommerce-Tabs-panel--description h3,
.woocommerce-Tabs-panel--description h4 {
	font-size: var(--wp--preset--font-size--lg);
	margin: var(--wp--preset--spacing--40) 0 var(--wp--preset--spacing--20);
}

.woocommerce-Tabs-panel--description > :first-child {
	margin-top: 0;
}

.woocommerce-Tabs-panel--description ul,
.woocommerce-Tabs-panel--description ol {
	margin: 0 0 var(--wp--preset--spacing--30);
	padding-left: 1.25em;
}

.woocommerce-Tabs-panel--description li {
	margin-bottom: 4px;
}

/* Lead-time pill used inside product grids. */
.i3d-badge {
	display: inline-block;
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--primary-deep);
	font-weight: 600;
	font-size: 0.8125rem;
	border-radius: var(--wp--custom--radius--pill);
	padding: 6px 14px;
}

/* Dark footer: muted links, white on hover. */
.i3d-footer a {
	color: var(--wp--preset--color--neutral-400);
}

.i3d-footer a:hover {
	color: var(--wp--preset--color--base);
}

/* Cart link as an outlined pill, per the design's "Cart · 0".
   Replaces the block mini-cart — see theme/inc/cart-link.php for why. The
   count is refreshed by WooCommerce cart fragments, so it stays correct even
   when the surrounding page is served from the LiteSpeed cache. */
.i3d-cart-link {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	border: 2px solid var(--wp--preset--color--contrast);
	border-radius: var(--wp--custom--radius--pill);
	padding: 7px 16px;
	font-weight: 600;
	font-size: var(--wp--preset--font-size--sm);
	line-height: 1;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	white-space: nowrap;
}

.i3d-cart-link:hover,
.i3d-cart-link:focus {
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	text-decoration: none;
}

.i3d-cart-link__icon {
	width: 17px;
	height: 17px;
	fill: currentColor;
	flex: none;
}

/* The shortcode block can arrive wrapped in a paragraph depending on how the
   template part is filtered. Strip the spacing rather than depend on it. */
.i3d-cart-slot,
.i3d-cart-slot p {
	margin: 0;
	padding: 0;
}

/* "Custom orders" is the header's call to action, styled as the pill button it
   replaced. There were two links to /custom-orders/ in the header — this menu
   item and a separate "Start a custom order" button — so the button went and
   its appearance moved here.

   Padding matches the button that was removed (11px/20px at the sm size) so
   the header's proportions are unchanged. Colours mirror theme.json's button
   element; if those tokens move, move these too.

   The doubled class is not a typo. Core ships
   `.wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content { color: inherit }`
   specifically to stop menu links taking a link colour, and at three classes
   it outranks a plain `.i3d-nav-cta > …` rule — so the label inherited the
   nav's dark text and sat unreadably on the blue. Matching core's doubling and
   adding the nav class puts this ahead of it. */
.wp-block-navigation .i3d-nav-cta > .wp-block-navigation-item__content.wp-block-navigation-item__content {
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	border-radius: var(--wp--custom--radius--pill);
	padding: 11px 20px;
}

.wp-block-navigation .i3d-nav-cta > .wp-block-navigation-item__content.wp-block-navigation-item__content:hover,
.wp-block-navigation .i3d-nav-cta > .wp-block-navigation-item__content.wp-block-navigation-item__content:focus {
	background: var(--wp--preset--color--primary-deep);
	color: var(--wp--preset--color--base);
}

/* Centre the Shop submenu under its parent item.

   Core anchors the dropdown to one edge rather than centring it, and because
   this nav is justified right it pins the panel to right:0 — so the submenu's
   200px minimum width hangs out to the left of a short label like "Shop".

   Desktop only. Inside the mobile overlay the submenu is statically
   positioned, and a transform there would shove it sideways rather than
   centre it — core resets left/right for the overlay but not transform.

   The selector has to out-specify core's own four-class
   .items-justified-right rule, which is why it is scoped to the header. */
@media (min-width: 600px) {
	.i3d-sticky-header .wp-block-navigation.items-justified-right .wp-block-navigation__container .has-child > .wp-block-navigation__submenu-container {
		left: 50%;
		right: auto;
		transform: translateX(-50%);
	}
}

/* Mobile overlay menu.

   The nav is justified right so the desktop bar sits against the CTA, and core
   reuses that same justification inside the overlay — which squeezes a
   full-screen menu into a right-hand edge instead of laying it out as a list.
   Everything below overrides that for the overlay only; the desktop bar is
   untouched.

   Opaque background stated explicitly: core sets the overlay to
   `background-color: inherit`, and the sticky header it inherits from is a
   translucent rgba, so the page shows through the menu. */
@media (max-width: 599.98px) {
	/* The blur has to go at this width, and it is not a cosmetic preference.
	   A `backdrop-filter` other than `none` makes the element a containing
	   block for `position: fixed` descendants — the same rule `transform` and
	   `filter` follow. The overlay menu is `position: fixed; inset: 0`, so with
	   the blur present its "full screen" resolved against the header's own box:
	   the menu was trapped at header height and core's `overflow: auto` turned
	   the items into an internal scroll. It also kept the overlay's
	   z-index: 100000 stuck inside the header's stacking context.

	   Desktop keeps the frosted header — the overlay never opens there. */
	.i3d-sticky-header {
		-webkit-backdrop-filter: none;
		backdrop-filter: none;
	}

	.i3d-sticky-header .wp-block-navigation__responsive-container.is-menu-open {
		background-color: var(--wp--preset--color--base);
	}

	.i3d-sticky-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content,
	.i3d-sticky-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
		align-items: stretch;
		width: 100%;
	}

	.i3d-sticky-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
		align-items: stretch;
		width: 100%;
		border-bottom: 1px solid var(--wp--preset--color--neutral-200);
	}

	/* box-sizing is load-bearing: with width:100% and horizontal padding, a
	   content-box element ends up wider than the screen and its label is cut
	   off at the right edge. The top-level items escape it only because their
	   horizontal padding is zero — the CTA below has 20px and does not. */
	.i3d-sticky-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
		display: block;
		width: 100%;
		box-sizing: border-box;
		padding: 10px 0;
		font-size: var(--wp--preset--font-size--md);
		text-align: left;
	}

	/* The CTA keeps its button shape in the overlay, but full width and
	   centred — the list rules above would otherwise leave it as a blue bar
	   with its label jammed against the left edge. Separator removed: it is a
	   button, not another row in the list. */
	.i3d-sticky-header .wp-block-navigation__responsive-container.is-menu-open .i3d-nav-cta {
		border-bottom: none;
		margin-top: var(--wp--preset--spacing--20);
	}

	.i3d-sticky-header .wp-block-navigation__responsive-container.is-menu-open .i3d-nav-cta > .wp-block-navigation-item__content {
		padding: 12px 20px;
		text-align: center;
	}

	/* Submenu reads as an indented list under its parent, not a dropdown.
	   Core already makes it static in the overlay; this is presentation only. */
	.i3d-sticky-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
		align-items: stretch;
		width: 100%;
		padding-left: var(--wp--preset--spacing--30);
	}

	.i3d-sticky-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item:last-child {
		border-bottom: none;
	}

	.i3d-sticky-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
		font-size: var(--wp--preset--font-size--sm);
		font-weight: 500;
		color: var(--wp--preset--color--neutral-600);
		padding: 8px 0;
	}
}

/* Links on the purple announcement bar: white and underlined —
   the default primary-deep link colour is illegible on secondary. */
.i3d-announce a {
	color: var(--wp--preset--color--base);
	text-decoration: underline;
}

/* Category-card titles are links but must read as card titles:
   contrast colour, no underline. The card itself signals hover. */
.i3d-hover-card h3 a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

/* Product cards read left-aligned per the design; text children get
   side padding (the image stays flush to the card edges). */
.wp-block-woocommerce-product-collection li.wc-block-product > :not(figure),
.wp-block-woocommerce-product-collection li.product > :not(figure) {
	margin-left: var(--wp--preset--spacing--30);
	margin-right: var(--wp--preset--spacing--30);
}

.wp-block-woocommerce-product-collection li.wc-block-product .wp-element-button,
.wp-block-woocommerce-product-collection li.product .wp-element-button {
	display: block;
	width: 100%;
	text-align: center;
}

/* Uniform "View product" call to action on every product card.
   Replaces woocommerce/product-button, which varied its label and behaviour by
   product type — "Add to cart" on simple products (adding straight to the cart
   over AJAX, unconfigured), "Select options" on variable ones, "Read more" on
   anything unpurchasable. Everything here is made to order and most items carry
   a colour or personalisation choice, so the archive should never be a buying
   surface: every card sends the customer to the product page.

   core/read-more resolves the permalink from the loop context, the same way the
   post-title block above it does. Values mirror theme.json's button element, so
   these cards stay visually identical to the real buttons elsewhere — if the
   button tokens change there, change them here too. */
/* No width: 100% here. The card gives every non-figure child 16px side
   margins, so a 100%-wide child comes out 32px wider than the card and gets
   its pill ends clipped by the card's overflow: hidden. The old
   woocommerce/product-button got away with it because it rendered a wrapper
   div that took the margins, with the <a> at 100% inside. core/read-more is a
   bare <a>, so it takes both — and a block element already fills the width
   that the margins leave. */
.i3d-view-product {
	display: block;
	box-sizing: border-box;
	text-align: center;
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	border-radius: var(--wp--custom--radius--pill);
	padding: 0.9375rem 2rem;
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	text-decoration: none;
}

.i3d-view-product:hover,
.i3d-view-product:focus {
	background: var(--wp--preset--color--primary-deep);
	color: var(--wp--preset--color--base);
	text-decoration: none;
}

.wp-block-woocommerce-product-collection del {
	color: var(--wp--preset--color--neutral-400);
	font-size: 1rem;
}

/* ---- Immersive motion layer (Design round trip 4) ----
   All animation is scoped to i3d- classes and disabled together under
   prefers-reduced-motion. Scroll reveals use animation-timeline: view();
   browsers without support run the time-based animation once on load,
   which degrades to "content visible" — safe either way. */

@keyframes i3d-print-build {
	from { clip-path: inset(100% 0 0 0); }
	to   { clip-path: inset(0 0 0 0); }
}

@keyframes i3d-print-head {
	from { top: 100%; }
	to   { top: -4px; }
}

@keyframes i3d-print-vanish {
	to { opacity: 0; }
}

@keyframes i3d-filament-scroll {
	to { background-position-x: 1280px; }
}

@keyframes i3d-rise {
	from { opacity: 0; transform: translateY(26px); }
}

@keyframes i3d-pulse {
	0%, 100% { opacity: 1; }
	50%      { opacity: 0.35; }
}

/* Hero headline "prints" in, with a glowing print-head line sweeping up.
   Replayable: hero-replay.js retriggers it on click and every 30s by
   toggling the class — keep all timing on the class, none on the bare h1. */
h1.i3d-print-reveal {
	position: relative;
	animation: i3d-print-build 2.8s 0.2s steps(14, jump-none) both;
}

h1.i3d-print-reveal::after {
	content: "";
	position: absolute;
	left: -4%;
	width: 108%;
	height: 3px;
	border-radius: var(--wp--custom--radius--pill);
	background: linear-gradient(90deg, transparent, #7ea6ff 20%, #ffffff 50%, #7ea6ff 80%, transparent);
	box-shadow: 0 0 18px rgba(126, 166, 255, 0.9);
	animation: i3d-print-head 2.8s 0.2s steps(14, jump-none) both, i3d-print-vanish 0.5s 3s both;
}

/* Radial glow behind the hero, layered over the print-line texture. */
.i3d-hero-glow {
	background-image: radial-gradient(640px 320px at 50% 12%, rgba(31, 139, 255, 0.16), transparent), repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.045) 0 1px, transparent 1px 9px) !important;
}

/* Filament strip drifts slowly sideways. */
.i3d-filament {
	background-size: 1280px 100%;
	background-repeat: repeat-x;
	animation: i3d-filament-scroll 48s linear infinite;
}

/* Sections rise in as they enter the viewport. */
.i3d-rise {
	animation: i3d-rise 0.7s both;
	animation-timeline: view();
	animation-range: entry 0% entry 40%;
}

/* Hover lift upgraded: cards float, not just shadow. */
.i3d-hover-card:hover,
.wp-block-woocommerce-product-collection li.wc-block-product:hover,
.wp-block-woocommerce-product-collection li.product:hover {
	transform: translateY(-4px);
	box-shadow: var(--wp--preset--shadow--lifted);
}

.i3d-hover-card,
.wp-block-woocommerce-product-collection li.wc-block-product,
.wp-block-woocommerce-product-collection li.product {
	transition: transform 0.3s ease, box-shadow 0.3s ease;
}

/* Filament swatch strip ("Pick your colour"). */
.i3d-swatches {
	display: flex;
	gap: 20px;
	justify-content: center;
	flex-wrap: wrap;
}

.i3d-swatch {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	width: 64px;
}

.i3d-swatch > div {
	width: 44px;
	height: 44px;
	border-radius: var(--wp--custom--radius--pill);
	transition: transform 0.2s ease;
}

.i3d-swatch:hover > div {
	transform: scale(1.2);
}

.i3d-swatch span {
	font-size: 0.75rem;
	color: var(--wp--preset--color--neutral-600);
	text-align: center;
}

@media (prefers-reduced-motion: reduce) {
	h1.i3d-print-reveal,
	h1.i3d-print-reveal::after,
	.i3d-filament,
	.i3d-rise,
	.i3d-swatch > div,
	.i3d-hover-card,
	.wp-block-woocommerce-product-collection li.wc-block-product,
	.wp-block-woocommerce-product-collection li.product {
		animation: none !important;
		transition: none !important;
	}
}

/* Off-brand plugin accent colours, overridden with tokens. YITH ships
   maroon (#A7144C) filter accents and teal (#03bfac) add-on accents;
   both take CSS custom properties, so re-point them at primary. */
:root {
	--yith-wcan-filters_colors_accent: var(--wp--preset--color--primary) !important;
	--yith-wcan-labels_style_background_hover: var(--wp--preset--color--primary) !important;
	--yith-wcan-labels_style_background_active: var(--wp--preset--color--primary) !important;
	--yith-wapo-accent-color-color: var(--wp--preset--color--primary) !important;
}

/* Product cards: the design draft wraps every product in a bordered white
   card with clipped corners and a shadow lift on hover. Product Collection
   markup offers no per-item styling, so the chrome lives here.

   Cards are flex columns so that titles wrapping to two lines, or a sale
   price adding a struck-through line, don't leave the buttons at different
   heights across a row — the button is pushed to the bottom instead. */
.wp-block-woocommerce-product-collection li.wc-block-product,
.wp-block-woocommerce-product-collection li.product {
	display: flex;
	flex-direction: column;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--neutral-200);
	border-radius: var(--wp--custom--radius--md);
	overflow: hidden;
	padding-bottom: var(--wp--preset--spacing--30);
	transition: box-shadow 0.2s ease;
}

/* Last child is the add-to-cart button; auto margin drives it to the
   bottom of whatever height the row settles at. */
.wp-block-woocommerce-product-collection li.wc-block-product > :last-child,
.wp-block-woocommerce-product-collection li.product > :last-child {
	margin-top: auto;
}

/* Uniform image height regardless of the source photo's proportions. */
.wp-block-woocommerce-product-collection li.wc-block-product img,
.wp-block-woocommerce-product-collection li.product img {
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: cover;
}

.wp-block-woocommerce-product-collection li.wc-block-product:hover,
.wp-block-woocommerce-product-collection li.product:hover {
	box-shadow: var(--wp--preset--shadow--card);
}

/* The card clips its own corners; images inside sit flush. */
.wp-block-woocommerce-product-collection li.wc-block-product img,
.wp-block-woocommerce-product-collection li.product img {
	border-radius: 0;
}

/* Custom Orders page (page-custom-orders.html). The intricate grids there
   are wp:html blocks; these classes carry their layout. */
.i3d-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: var(--wp--preset--spacing--30);
}

.i3d-step-card,
.i3d-cap-card,
.i3d-tier-card {
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--neutral-200);
	border-radius: var(--wp--custom--radius--md);
	overflow: hidden;
}

.i3d-step-card,
.i3d-tier-card {
	padding: var(--wp--preset--spacing--40);
}

.i3d-num {
	width: 40px;
	height: 40px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--primary-deep);
	font-weight: 700;
	display: flex;
	align-items: center;
	justify-content: center;
	margin-bottom: var(--wp--preset--spacing--20);
}

.i3d-faq details {
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--neutral-200);
	border-radius: var(--wp--custom--radius--md);
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
}

.i3d-faq summary {
	font-weight: 700;
	cursor: pointer;
}

.i3d-faq p {
	margin: var(--wp--preset--spacing--20) 0 0;
	color: var(--wp--preset--color--neutral-600);
}

/* ---- Classic WooCommerce surfaces (cart, checkout, my-account) ----
   These pages run the classic shortcodes for YITH and gateway
   compatibility, so their styling lives here rather than in blocks. */

/* Tables (cart contents, order review, my-account orders) as cards. */
.woocommerce table.shop_table {
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--neutral-200);
	border-radius: var(--wp--custom--radius--md);
	border-collapse: separate;
	border-spacing: 0;
	overflow: hidden;
}

.woocommerce table.shop_table th {
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
	background: var(--wp--preset--color--neutral-100);
}

.woocommerce table.shop_table td,
.woocommerce table.shop_table th {
	border-bottom: 1px solid var(--wp--preset--color--neutral-200);
	padding: 12px 16px;
}

.woocommerce table.shop_table tr:last-child td {
	border-bottom: none;
}

/* Buttons: pill, primary, consistent with the theme button element. */
.woocommerce .button,
.woocommerce button.button,
.woocommerce a.button,
.woocommerce input.button,
.woocommerce #respond input#submit,
.wc-proceed-to-checkout a.checkout-button,
.woocommerce-cart-form button[name="update_cart"],
.woocommerce #payment #place_order {
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	font-family: inherit;
	font-weight: 600;
	border: none;
	border-radius: var(--wp--custom--radius--pill);
	padding: 12px 24px;
	cursor: pointer;
	transition: background 0.2s ease;
}

.woocommerce .button:hover,
.woocommerce button.button:hover,
.woocommerce a.button:hover,
.woocommerce #payment #place_order:hover {
	background: var(--wp--preset--color--primary-deep);
	color: var(--wp--preset--color--base);
}

.woocommerce .button:disabled,
.woocommerce button.button:disabled {
	background: var(--wp--preset--color--neutral-200);
	color: var(--wp--preset--color--neutral-400);
}

/* Form fields across checkout, coupon, login and account forms. */
.woocommerce .input-text,
.woocommerce select,
.woocommerce textarea,
.woocommerce input[type="text"],
.woocommerce input[type="email"],
.woocommerce input[type="tel"],
.woocommerce input[type="password"],
.woocommerce input[type="number"] {
	font-family: inherit;
	font-size: 1rem;
	padding: 10px 14px;
	border: 1px solid var(--wp--preset--color--neutral-400);
	border-radius: var(--wp--custom--radius--sm);
	background: var(--wp--preset--color--base);
}

.woocommerce .input-text:focus,
.woocommerce select:focus,
.woocommerce textarea:focus {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 1px;
}

.woocommerce form .form-row label {
	font-weight: 600;
	font-size: var(--wp--preset--font-size--sm);
}

/* Cart quantity input stays compact. */
.woocommerce .quantity .qty {
	width: 4.5em;
	text-align: center;
}

/* Cart totals and checkout payment panel as a soft card. */
.woocommerce .cart-collaterals .cart_totals,
.woocommerce-checkout #payment {
	background: var(--wp--preset--color--neutral-100);
	border-radius: var(--wp--custom--radius--md);
	padding: var(--wp--preset--spacing--40);
}

.woocommerce-checkout #payment {
	border: none;
}

.woocommerce-checkout #payment div.payment_box {
	background: var(--wp--preset--color--base);
	border-radius: var(--wp--custom--radius--sm);
}

/* Notices mapped to semantic tokens. */
.woocommerce-message,
.woocommerce-info,
.woocommerce-error {
	border-radius: var(--wp--custom--radius--sm);
	border-top: none;
	font-weight: 600;
}

.woocommerce-message {
	background: var(--wp--preset--color--success-bg);
	color: var(--wp--preset--color--success);
}

.woocommerce-info {
	background: var(--wp--preset--color--info-bg);
	color: var(--wp--preset--color--info);
}

.woocommerce-error {
	background: var(--wp--preset--color--error-bg);
	color: var(--wp--preset--color--error);
}

/* My-account: navigation as pills, content breathing room. */
.woocommerce-MyAccount-navigation ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.woocommerce-MyAccount-navigation ul li a {
	display: block;
	padding: 10px 18px;
	border-radius: var(--wp--custom--radius--pill);
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.woocommerce-MyAccount-navigation ul li.is-active a,
.woocommerce-MyAccount-navigation ul li a:hover {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--primary-deep);
}

/* Login / register card on my-account when logged out. */
.woocommerce-form-login,
.woocommerce-form-register {
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--neutral-200);
	border-radius: var(--wp--custom--radius--md);
	padding: var(--wp--preset--spacing--40);
	max-width: 480px;
}

/* Fluent Forms, restyled to the design system. */
.fluentform input[type="text"],
.fluentform input[type="email"],
.fluentform input[type="number"],
.fluentform input[type="url"],
.fluentform select,
.fluentform textarea {
	font-family: inherit;
	font-size: 1rem;
	padding: 12px 16px;
	border: 1px solid var(--wp--preset--color--neutral-400);
	border-radius: var(--wp--custom--radius--sm);
	background: var(--wp--preset--color--base);
	width: 100%;
}

.fluentform input:focus,
.fluentform select:focus,
.fluentform textarea:focus {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 1px;
}

.fluentform .ff-el-input--label label {
	font-weight: 600;
	font-size: var(--wp--preset--font-size--sm);
}

.fluentform .ff-btn-submit {
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	font-family: inherit;
	font-weight: 600;
	font-size: 1.0625rem;
	border: none;
	border-radius: var(--wp--custom--radius--pill);
	padding: 15px 32px;
	cursor: pointer;
}

.fluentform .ff-btn-submit:hover {
	background: var(--wp--preset--color--primary-deep);
}

.fluentform .ff-message-success {
	background: var(--wp--preset--color--success-bg);
	color: var(--wp--preset--color--success);
	border-radius: var(--wp--custom--radius--sm);
	padding: 12px 16px;
	font-weight: 600;
}
