/* Credphone — global UI foundation (CP-004). Consumes theme.json design tokens. */

/* --- Global safety --- */

html {
	overflow-x: hidden;
}

/* --- Accessibility utilities --- */

.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.skip-link {
	position: absolute;
	top: 0;
	left: -9999px;
	z-index: 1000;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--paper);
	border-radius: 0 0 var(--wp--custom--radius--sm) 0;
	text-decoration: none;
	font-weight: 600;
}

.skip-link:focus {
	left: 0;
}

:focus-visible {
	outline: 2px solid var(--wp--preset--color--ink);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		scroll-behavior: auto !important;
	}
}

/* --- States shared by interactive components --- */

[disabled],
.is-disabled,
[aria-disabled="true"] {
	opacity: 0.5;
	cursor: not-allowed;
	pointer-events: none;
}

/* --- Buttons --- */

.btn,
.credphone-shop-grid .wc-block-components-product-button__button {
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--wp--preset--spacing--20);
	min-height: 44px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
	border: 1px solid transparent;
	border-radius: var(--wp--custom--radius--md);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
	font-weight: 600;
	line-height: 1.2;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease, filter 150ms ease, transform 200ms ease, box-shadow 200ms ease;
}

/* Same root cause as .financing-hub__result-list[hidden] above: `.btn`'s
   own `display: inline-flex` ties the browser's native `[hidden] { display:
   none }` on specificity and wins by cascade order, so a JS-hidden .btn
   (confirmed live: the modal's own "Simular" button stayed visible and
   clickable with hidden="" set) never actually disappears. */
.btn[hidden] {
	display: none;
}

/* Premium hover: a soft gold halo + a small lift, scoped to real boxed
   buttons (not `.btn--text`, which has no fill/border for a halo to read
   against). Fluid transition comes from the shared `.btn` rule above. */
@media (hover: hover) and (pointer: fine) {
	.btn:not(.btn--text):hover,
	.credphone-shop-grid .wc-block-components-product-button__button:hover {
		transform: translateY(-1px) scale(1.02);
		box-shadow: 0 10px 22px color-mix(in srgb, var(--wp--preset--color--brand-gold) 30%, transparent);
	}
}

@media (prefers-reduced-motion: reduce) {
	.btn:not(.btn--text):hover,
	.credphone-shop-grid .wc-block-components-product-button__button:hover {
		transform: none;
		box-shadow: none;
	}
}

.btn--primary,
.credphone-shop-grid .wc-block-components-product-button__button {
	background: var(--wp--preset--color--brand-gold);
	border-color: var(--wp--preset--color--brand-gold);
	color: var(--wp--preset--color--ink);
}

.btn--primary:hover,
.credphone-shop-grid .wc-block-components-product-button__button:hover {
	filter: brightness(0.93);
}

.btn--primary:active,
.credphone-shop-grid .wc-block-components-product-button__button:active {
	filter: brightness(0.87);
}

.btn--secondary {
	background: transparent;
	border-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--ink);
}

.btn--secondary:hover {
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--paper);
}

.btn--secondary:active {
	background: color-mix(in srgb, var(--wp--preset--color--ink) 85%, black);
	border-color: color-mix(in srgb, var(--wp--preset--color--ink) 85%, black);
}

.btn--text {
	background: transparent;
	border-color: transparent;
	color: var(--wp--preset--color--ink);
	padding-inline: var(--wp--preset--spacing--20);
	text-decoration: underline;
	text-underline-offset: 3px;
}

.btn--text:hover {
	color: var(--wp--preset--color--brand-gold-700);
}

/* --- Icon buttons (header/footer utility controls) --- */

.icon-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	border-radius: var(--wp--custom--radius--sm);
	color: var(--wp--preset--color--ink);
	background: transparent;
	border: none;
	cursor: pointer;
	text-decoration: none;
	transition: background-color 150ms ease, color 150ms ease;
}

.icon-btn:hover {
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 25%, transparent);
}

/* --- Surfaces --- */

.card {
	background: var(--wp--preset--color--paper);
	border: var(--wp--custom--elevation--border);
	border-radius: var(--wp--custom--radius--md);
	padding: var(--wp--preset--spacing--50);
}

.card--raised {
	border-color: transparent;
	box-shadow: var(--wp--custom--elevation--raised);
}

/* --- Badges / chips --- */

.badge {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	border-radius: var(--wp--custom--radius--pill);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	line-height: 1;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--paper);
}

.badge--success {
	background: var(--wp--preset--color--success);
}

.badge--warning {
	background: var(--wp--preset--color--warning);
}

.badge--error {
	background: var(--wp--preset--color--error);
}

.badge--info {
	background: var(--wp--preset--color--info);
}

/* --- Notices / status messages --- */

.notice {
	--notice-color: var(--wp--preset--color--info);
	display: flex;
	gap: var(--wp--preset--spacing--30);
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--50);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
	border-left: 4px solid var(--notice-color);
	border-radius: var(--wp--custom--radius--sm);
}

.notice--success {
	--notice-color: var(--wp--preset--color--success);
}

.notice--warning {
	--notice-color: var(--wp--preset--color--warning);
}

.notice--error {
	--notice-color: var(--wp--preset--color--error);
}

.notice--info {
	--notice-color: var(--wp--preset--color--info);
}

/* Same root cause as .btn[hidden]/.financing-hub__result-list[hidden]: the
   base .notice rule's own `display: flex` ties [hidden] on specificity and
   wins by cascade order (confirmed live on the financing modal's
   data-fpm-no-profile notice, which stayed visible with hidden="" set). */
.notice[hidden] {
	display: none;
}

/* --- Forms --- */

.form-input,
.form-select {
	box-sizing: border-box;
	display: block;
	width: 100%;
	min-height: 44px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
}

.form-input::placeholder {
	color: color-mix(in srgb, var(--wp--preset--color--ink) 55%, var(--wp--preset--color--paper));
}

/* Same class of bug as .wc-block-cart-item__image img[hidden] elsewhere in
   this file: author-origin `display: block` above beats the UA
   stylesheet's `[hidden] { display: none }` regardless of specificity, so
   a hidden `hidden` attribute on any `.form-input`/`.form-select` (e.g.
   financing-hub.js hiding the Prestações select when no term is available)
   had no visible effect without this. */
.form-input[hidden],
.form-select[hidden] {
	display: none;
}

.form-input:focus-visible,
.form-select:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 1px;
	border-color: var(--wp--preset--color--brand-gold-700);
}

input[type="checkbox"],
input[type="radio"] {
	accent-color: var(--wp--preset--color--ink);
	width: 20px;
	height: 20px;
}

/* --- Price --- */

.price {
	font-weight: 700;
	font-size: var(--wp--preset--font-size--xl);
	font-variant-numeric: tabular-nums;
	color: var(--wp--preset--color--ink);
}

.price__original {
	font-weight: 400;
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
	text-decoration: line-through;
	margin-inline-start: var(--wp--preset--spacing--20);
}

/* --- Section / container spacing --- */

.section {
	padding-block: var(--wp--preset--spacing--70);
}

/* --- Page shell --- */

.site-main {
	padding-block: var(--wp--preset--spacing--70) var(--wp--preset--spacing--80);
	min-height: 40vh;
	/* CP-018: this theme's constrained layout has zero built-in horizontal
	   padding below 1280px (confirmed live — content genuinely touches the
	   viewport edge site-wide, not a per-template bug). One systemic content
	   gutter here covers Shop/Product/Account/Financing/Home uniformly
	   instead of patching each template separately. The hero's own
	   full-bleed background is unaffected — its `alignfull` breakout is
	   viewport-relative, not dependent on this ancestor's padding.
	   CP-039b: this used to drop straight to 0 at >=1280px, trusting
	   WordPress's own max-width:1280px + margin:auto to supply outside
	   whitespace instead. That whitespace is just (viewport-1280)/2 per
	   side, which is genuinely thin across the common laptop range the PO
	   tested live (1280/1366/1536px — as little as 0px at exactly 1280,
	   ~43px at 1366) even though it looks fine on an actual wide desktop.
	   Keeping this gutter through 1599px fixes every laptop width without
	   visibly changing anything >=1600px, where the auto-margin alone is
	   already generous (>=160px/side). */
	padding-inline: var(--wp--preset--spacing--50);
}

@media (min-width: 1600px) {
	.site-main {
		padding-inline: 0;
	}
}

/* --- Site header --- */

/* WordPress wraps every `wp:template-part` in a `.wp-block-template-part`
   div sized to exactly its single child's height (109px, matching the
   header). `position: sticky`'s containing block is that immediate parent,
   not the much-taller `.wp-site-blocks` — with zero extra height to move
   within, the header could never actually detach and stick; it just
   scrolled away with the page (verified: scrolling 1px already broke it,
   both logged in and out, pre-existing, not caused by any change in this
   pass). `display: contents` removes the wrapper's own box from layout so
   `.site-header`'s containing block becomes `.wp-site-blocks` instead. */
.site-header-slot {
	display: contents;
}

.site-header {
	position: sticky;
	/* WP core sets this custom property on the root element only when the
	   admin bar is present (32px desktop / 46px <783px) — falls back to 0
	   for logged-out visitors, keeping the header flush with the viewport
	   top exactly as before for the common case. */
	top: var(--wp-admin--admin-bar--height, 0px);
	z-index: 40;
	background: var(--wp--preset--color--paper);
	border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
}

/* Commerce header: dark surface (§6/§7 of the CP-016 visual-overhaul plan).
   The real logo is a white + brand-gold mark with no black in it — on the
   previous white header the white half was invisible. `.site-header--checkout`
   is excluded here only because it gets its OWN, near-identical dark rule
   below (distraction-free layout — no nav/search/category row — but CP-019
   made it visually consistent with this dark surface too, reversing the
   original CP-008 "stays light/quiet" decision after user approval). */
.site-header:not(.site-header--checkout) {
	background: var(--wp--custom--surface--inverse);
	color: var(--wp--custom--text--on-inverse);
	border-bottom: 1px solid var(--wp--custom--border--on-inverse);
}

.site-header:not(.site-header--checkout) .site-header__actions {
	border-left-color: var(--wp--custom--border--on-inverse);
}

/* CP-021: rest-state intensity toned down to the same approved "muted"
   token this header already uses for the utility row (line ~454) — still
   9.6:1 against the dark header (well past the 3:1 AA floor for icon/UI
   components), just quieter than full-white so hover/focus reads as a
   deliberate gain in contrast, not a coin-flip between two equally loud
   states. */
.site-header:not(.site-header--checkout) .icon-btn,
.site-header:not(.site-header--checkout) .wp-block-woocommerce-customer-account,
.site-header:not(.site-header--checkout) .wc-block-customer-account__link,
.site-header:not(.site-header--checkout) .wc-block-mini-cart__button,
.site-header:not(.site-header--checkout) .wc-block-mini-cart__icon {
	color: var(--wp--custom--text--on-inverse-muted);
}

/* CP-028: circular icon-button language for the utility controls (search
   toggle, wishlist, account, cart) — previously plain icons with zero
   surface, "loose" against the dark header. A subtle light-on-dark wash +
   hairline border reads as a real control at rest; hover already turns
   solid gold via the rule below. Scoped to `.site-header__actions` only —
   the mobile hamburger/search-toggle wrapper isn't affected, and this never
   touches the generic `.icon-btn` used elsewhere (e.g. the card quantity
   stepper, which must stay square to nest inside its own pill). */
.site-header__actions .icon-btn,
.site-header__actions .wp-block-woocommerce-customer-account,
.site-header__actions .wc-block-mini-cart__button {
	border-radius: var(--wp--custom--radius--pill);
	background: color-mix(in srgb, var(--wp--custom--text--on-inverse) 10%, transparent);
	border: 1px solid var(--wp--custom--border--on-inverse);
}

/* CP-019: was a 22% brand-gold/dark-surface mix — read as a dull "burnt"
   tone rather than the bright primary yellow used on CTA buttons. Solid
   bright pill + dark icon, same treatment as .btn--primary. Keyboard focus
   gets the identical treatment (not just the outline ring below) so
   focus-visible is a genuine contrast gain over the muted rest state,
   matching what a mouse hover already gets. */
.site-header:not(.site-header--checkout) .icon-btn:hover,
.site-header:not(.site-header--checkout) .icon-btn:focus-visible,
.site-header:not(.site-header--checkout) .wp-block-woocommerce-customer-account:hover,
.site-header:not(.site-header--checkout) .wp-block-woocommerce-customer-account:focus-within,
.site-header:not(.site-header--checkout) .wc-block-mini-cart__button:hover,
.site-header:not(.site-header--checkout) .wc-block-mini-cart__button:focus-visible {
	background: var(--wp--preset--color--brand-gold);
	color: var(--wp--preset--color--ink);
}

/* WooCommerce's mini-cart Interactivity API reads this element's *own*
   `color`/`background-color` at hydration and swaps them into the inline
   style it actually renders with (badgeBackgroundColor <- computed `color`,
   badgeTextColor <- computed `background-color`, see mini-cart.js) — so the
   values below are intentionally the inverse of the visible result (gold
   pill, ink number, matching the sitewide badge convention). A permanent
   ring in the header's own surface colour keeps the badge visually
   separated from the icon glyph at rest; on hover/focus the button itself
   turns solid gold (rule above), which would otherwise swallow an
   identically-gold badge, so that state gets its own `!important` override
   (WC's inline style otherwise wins) that flips the badge to ink-on-gold —
   the exact inverse pairing — so it stays legible against the pill. */
.site-header:not(.site-header--checkout) .wc-block-mini-cart__badge {
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--brand-gold);
	box-shadow: 0 0 0 2px var(--wp--custom--surface--inverse);
}

.site-header:not(.site-header--checkout) .wc-block-mini-cart__button:hover .wc-block-mini-cart__badge,
.site-header:not(.site-header--checkout) .wc-block-mini-cart__button:focus-visible .wc-block-mini-cart__badge {
	background: var(--wp--preset--color--ink) !important;
	color: var(--wp--preset--color--brand-gold) !important;
	box-shadow: 0 0 0 2px var(--wp--preset--color--brand-gold);
}

/* The global :focus-visible ring is ink-on-ink here — invisible. Every
   focusable header control needs the inverted ring instead. */
.site-header:not(.site-header--checkout) a:focus-visible,
.site-header:not(.site-header--checkout) button:focus-visible,
.site-header:not(.site-header--checkout) summary:focus-visible,
.site-header:not(.site-header--checkout) input:focus-visible {
	outline-color: var(--wp--preset--color--brand-gold);
}

/* CP-019: desktop-only utility row. Hidden by default (mobile/tablet keep
   the exact CP-018 header, nothing added there); shown only at the same
   1024px breakpoint the rest of this header already treats as "desktop".
   `.site-header` prefix (2 classes) is required, not just `.site-header__utility`
   alone (1 class) — Gutenberg's own `.is-layout-flex { display: flex }` core
   rule is equal specificity, so a single-class override loses to it
   regardless of source order (the same recurring pattern documented
   elsewhere in this file for `[hidden]` vs. author-origin `display`). */
.site-header .site-header__utility {
	display: none;
}

/* CP-021 fix: root cause of a white gap rendering above the ENTIRE page on
   mobile — confirmed live via computed styles, not guessed. Gutenberg's
   block-gap margin on `.site-header__row` (the flex gap between it and
   `.site-header__utility`) is written against DOM position — it doesn't
   check whether the preceding sibling is actually visible — so hiding
   `.site-header__utility` with `display:none` above still left
   `.site-header__row` with a 24px `margin-top`. `.site-header` has no
   padding/border to act as a collapse boundary, so that margin collapsed
   straight through the sticky header and `<body>`, rendering as blank
   space between the viewport top and the header (confirmed live:
   `.site-header__row`'s own computed `margin-top` was 24px while every
   ancestor up to `<body>` reported 0, and `document.body`'s own
   `getBoundingClientRect().top` was 24 — the classic signature of a
   margin collapsing out through an unguarded ancestor chain). Below
   1024px `.site-header__row` genuinely is the first visible header
   block, so its top margin must be 0 there; restored to the theme's own
   block-gap value once the utility row becomes visible again at 1024px. */
.site-header__row {
	margin-top: 0;
}

@media (min-width: 1024px) {
	.site-header .site-header__utility {
		display: flex;
		align-items: center;
		padding-block: var(--wp--preset--spacing--20);
		/* CP-039b: same gutter floor as `.site-header__row` just below —
		   this row never had its own horizontal padding either. */
		padding-inline: var(--wp--preset--spacing--50);
		border-bottom: 1px solid var(--wp--custom--border--on-inverse);
		font-size: var(--wp--preset--font-size--sm);
	}

	.site-header__utility-right {
		gap: var(--wp--preset--spacing--50);
	}

	/* Secondary, factual trust line — never competes visually with
	   "Apoio ao cliente" (a real link/action) or the primary nav below. */
	.site-header__trust {
		margin: 0;
		color: color-mix(in srgb, var(--wp--custom--text--on-inverse) 62%, transparent);
		font-size: var(--wp--preset--font-size--sm);
		white-space: nowrap;
	}

	.site-header__utility-link {
		background: none;
		border: none;
		padding: 0;
		color: color-mix(in srgb, var(--wp--custom--text--on-inverse) 75%, transparent);
		font-family: inherit;
		font-size: inherit;
		text-decoration: none;
		cursor: pointer;
	}

	/* Utility action, not a CTA — hover goes to full-opacity white, never
	   brand-gold (that stays reserved for real purchase/accent moments per
	   DESIGN.md), and never underlines. */
	a.site-header__utility-link:hover {
		color: var(--wp--custom--text--on-inverse);
	}

	.site-header__utility-link.is-disabled {
		cursor: not-allowed;
	}

	.site-header__row {
		margin-top: var(--wp--style--block-gap, 24px);
	}
}

.site-language-switcher {
	position: relative;
}

.site-language-switcher__toggle {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: 36px;
	padding: 4px;
	border: 0;
	border-radius: var(--wp--custom--radius--sm);
	background: transparent;
	color: var(--wp--custom--text--on-inverse-muted);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 650;
	line-height: 1.2;
	cursor: pointer;
	transition: color 150ms ease, background-color 150ms ease;
}

.site-language-switcher__toggle:hover,
.site-language-switcher__toggle[aria-expanded="true"] {
	background: color-mix(in srgb, var(--wp--preset--color--white) 8%, transparent);
	color: var(--wp--preset--color--brand-gold);
}

.site-language-switcher__toggle svg {
	flex: none;
	transition: transform 150ms ease;
}

.site-language-switcher__toggle[aria-expanded="true"] svg {
	transform: rotate(180deg);
}

.site-language-switcher__flag {
	display: block;
	flex: none;
	width: 20px;
	height: 14px;
	border-radius: 2px;
	object-fit: cover;
}

.site-language-switcher__menu {
	position: absolute;
	z-index: 100;
	top: calc(100% + 6px);
	left: 0;
	display: grid;
	min-width: 100%;
	margin: 0;
	padding: 4px;
	border: 1px solid var(--wp--custom--border--on-inverse);
	border-radius: var(--wp--custom--radius--sm);
	background: var(--wp--preset--color--ink);
	box-shadow: 0 12px 28px rgb(0 0 0 / 28%);
	list-style: none;
	white-space: nowrap;
}

.site-language-switcher__menu[hidden] {
	display: none;
}

.site-language-switcher__menu a {
	/* CP-030: without this, `width: 100%` resolves against the parent `<li>`
	   on the browser's default `box-sizing: content-box`, then `padding-
	   inline: 10px` adds another 20px on top — confirmed live the item
	   rendered 20px wider than its own `<li>` (159.36px vs 139.36px),
	   letting the hover/[aria-current] background below poke past the
	   menu's rounded corner. border-box makes `width: 100%` include the
	   padding, so the item's box always matches its container's inset. */
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	min-height: 42px;
	padding-inline: 10px;
	border-radius: var(--wp--custom--radius--sm);
	color: var(--wp--custom--text--on-inverse-muted);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 650;
	text-decoration: none;
	transition: background-color 150ms ease, color 150ms ease;
}

.site-language-switcher__menu a:hover,
.site-language-switcher__menu a:focus-visible {
	background: color-mix(in srgb, var(--wp--preset--color--white) 8%, transparent);
	color: var(--wp--preset--color--white);
}

.site-language-switcher__menu a[aria-current="page"] {
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 16%, transparent);
	color: var(--wp--preset--color--brand-gold);
}

.site-language-switcher--mobile {
	display: flex;
	align-items: center;
	margin-inline-start: var(--wp--preset--spacing--20);
}

.site-language-switcher--mobile .site-language-switcher__menu {
	min-width: min(100%, calc(100vw - 32px));
}

@media (min-width: 1024px) {
	.site-language-switcher--mobile {
		display: none;
	}
}

@media (max-width: 1023px) {
	.site-language-switcher--desktop {
		display: none;
	}
}

.site-header__row {
	padding-block: var(--wp--preset--spacing--50);
	/* CP-039b: `.site-header` is a constrained-layout group (contentSize
	   1280px) with no padding of its own — unlike `.site-main`, this row
	   never had ANY horizontal gutter outside of 390px mobile, relying
	   entirely on WordPress's max-width:1280px + margin:auto for outside
	   whitespace. That auto-margin is thin across 1280-1536px (confirmed
	   live by the PO: logo/nav/search/cart sit almost flush with the
	   viewport edge at 1366x768/1536x864). Same systemic floor as
	   `.site-main`, zeroed out again >=1600px where the auto-margin alone
	   is already generous. */
	padding-inline: var(--wp--preset--spacing--50);
	gap: var(--wp--preset--spacing--40);
}

@media (min-width: 1600px) {
	.site-header__row {
		padding-inline: 0;
	}
}

.site-logo {
	display: inline-flex;
	align-items: center;
	flex-shrink: 0;
}

.site-logo img {
	height: 60px;
	width: auto;
	display: block;
	transition: transform 200ms ease;
}

/* Transform doesn't participate in layout, so the header row's height/gap
   never shifts and nothing needs `overflow` cleared for this to be
   visible — confirmed no ancestor between here and `<body>` clips
   overflow. */
@media (hover: hover) and (pointer: fine) {
	.site-logo:hover img,
	.site-logo:focus-visible img {
		transform: scale(1.08);
	}
}

@media (prefers-reduced-motion: reduce) {
	.site-logo:hover img,
	.site-logo:focus-visible img {
		transform: none;
	}
}

.site-header__actions {
	gap: var(--wp--preset--spacing--20);
	align-items: center;
	border-left: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
	padding-left: var(--wp--preset--spacing--40);
}

/* Primary navigation (core/navigation block) */

.site-nav.wp-block-navigation {
	flex-grow: 1;
}

.site-nav .wp-block-navigation-item__content {
	position: relative;
	display: inline-block;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	color: var(--wp--custom--text--on-inverse);
	font-weight: 600;
	letter-spacing: 0.01em;
	text-decoration: none;
	transition: color 150ms ease, transform 150ms ease;
}

.site-nav .wp-block-navigation-item__content::after {
	content: "";
	position: absolute;
	left: var(--wp--preset--spacing--40);
	right: var(--wp--preset--spacing--40);
	bottom: 6px;
	height: 2px;
	background: var(--wp--preset--color--brand-gold);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 150ms ease;
}

.site-nav .wp-block-navigation-item__content:hover,
.site-nav .wp-block-navigation-item__content:focus-visible {
	color: var(--wp--preset--color--brand-gold);
}

@media (hover: hover) and (pointer: fine) {
	.site-nav .wp-block-navigation-item__content:hover,
	.site-nav .wp-block-navigation-item__content:focus-visible {
		transform: scale(1.05);
	}
}

@media (prefers-reduced-motion: reduce) {
	.site-nav .wp-block-navigation-item__content:hover,
	.site-nav .wp-block-navigation-item__content:focus-visible {
		transform: none;
	}
}

.site-nav .wp-block-navigation-item__content:hover::after,
.site-nav .wp-block-navigation-item__content:focus-visible::after {
	transform: scaleX(1);
}

/* CP-021 Round 4 Gate 3: real "estado ativo" — server-set via functions.php's
   render_block_core/navigation-link filter (works with JS disabled too).
   Reuses the same gold underline the hover/focus state already draws,
   permanently visible rather than only on interaction, plus the brand
   color so it reads as "you are here" at a glance. */
.site-nav .wp-block-navigation-item__content.is-active {
	color: var(--wp--preset--color--brand-gold);
}

.site-nav .wp-block-navigation-item__content.is-active::after {
	transform: scaleX(1);
}

.site-nav .wp-block-navigation__responsive-container-open {
	min-width: 44px;
	min-height: 44px;
}

/* This wrapper div is always present in the DOM (not only while the mobile
   overlay is open) — scoping the background to .is-menu-open only is required,
   otherwise it paints an opaque panel behind the desktop inline nav too
   (invisible by coincidence on the old white header, opaque-white on the new
   dark one). */
/* Mobile/tablet nav overlay: dark, matching the header (§10 of the CP-016
   plan) — replaces the previous blank white scaffold panel. Color set on the
   dialog wrapper itself so the close/submenu-toggle icons (currentColor)
   inherit it without needing their own selectors. */
.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog {
	background: var(--wp--custom--surface--inverse);
	color: var(--wp--custom--text--on-inverse);
}

.site-nav .wp-block-navigation__responsive-container.is-menu-open a:focus-visible,
.site-nav .wp-block-navigation__responsive-container.is-menu-open button:focus-visible {
	outline-color: var(--wp--preset--color--brand-gold);
}

/* "Categorias" submenu — only reachable inside the overlay (its trigger
   carries .nav-overlay-only too, see above); children render as a nested
   list, indented and slightly smaller so they read as a sub-level rather
   than four more primary links. */
.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu .wp-block-navigation__submenu-container {
	position: static;
	background: transparent;
	box-shadow: none;
	padding-left: var(--wp--preset--spacing--40);
}

.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	font-size: var(--wp--preset--font-size--base);
	font-weight: 500;
	color: var(--wp--custom--text--on-inverse-muted);
}

.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	font-size: var(--wp--preset--font-size--lg);
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--50);
}

/* Search — a single real field at every breakpoint (DESIGN.md: search is a
   primary capability, never hidden behind an icon-only toggle). Below
   1024px it becomes its own full-width second header row; at >=1024px it
   sits inline between nav and the utility icons (unchanged from CP-008.2). */

.site-search {
	display: flex;
}

/* Mobile-only trigger for the collapsed/expanded search — hidden by
   default (desktop keeps the always-visible inline field, no toggle
   needed); shown only in the ≤781px rule below. */
.site-search-toggle {
	display: none;
}

/* Core Navigation only goes to its hamburger overlay below ~600px, but 5 nav
   items + logo + utilities don't fit one line before ~1024px, so the nav's
   own item list wrapped into 2 ragged lines and crowded the logo (confirmed
   live at 768px). Give the nav its own row instead of letting it wrap. */
.site-nav.wp-block-navigation .wp-block-navigation__container {
	flex-wrap: nowrap;
}

@media (max-width: 1023px) {
	.site-header__row {
		flex-wrap: wrap !important;
		row-gap: var(--wp--preset--spacing--20);
	}

	.site-search--inline {
		align-items: center;
		order: 5;
		flex: 1 1 100%;
		gap: var(--wp--preset--spacing--20);
	}

	.site-search--inline .form-input {
		flex: 1;
		min-width: 0;
	}
}

@media (min-width: 601px) and (max-width: 1023px) {
	.site-nav.wp-block-navigation {
		order: 3;
		flex: 1 1 100%;
		flex-grow: 0;
		/* CP-021 Round 4 Gate 3: `flex-basis: 100%` alone doesn't force this
		   onto its own row — `flex-shrink` (default 1, unset here) still
		   lets the browser shrink it back down and keep it sharing the row
		   with the logo/icons whenever that still technically fits.
		   Confirmed live: with 5 nav links (post-Financiamento) that shared
		   row no longer fits at 601-767px and started clipping/overflowing
		   horizontally — `min-width: 100%` is what actually guarantees the
		   own-row layout the surrounding comment already describes as the
		   intended design, at every item count. */
		min-width: 100%;
	}

	.site-nav .wp-block-navigation-item__content {
		padding-inline: var(--wp--preset--spacing--30);
	}
}

/* Width isn't hardcoded at desktop — it fills the room left between nav and
   utility icons, clamped so it never gets absurdly wide. */
@media (min-width: 1024px) {
	.site-nav.wp-block-navigation {
		flex-grow: 0;
	}

	/* CP-018: pill-shaped field with the search icon inside it (not a
	   separate floating control) — `position:relative` wrapper, the
	   existing submit `<button>` (same icon/markup, no new SVG) becomes an
	   absolutely-positioned overlay at the field's right edge. */
	.site-search--inline {
		position: relative;
		align-items: center;
		flex: 1 1 auto;
		min-width: 0;
		max-width: clamp(220px, 26vw, 380px);
	}

	.site-search--inline .form-input {
		width: 100%;
		border-radius: var(--wp--custom--radius--pill);
		padding-inline: var(--wp--preset--spacing--40) calc(var(--wp--preset--spacing--70) + var(--wp--preset--spacing--10, 4px));
	}

	/* CP-019: this icon now sits INSIDE the white pill field, not directly
	   on the dark header bg — it still inherited `color:
	   var(--text-on-inverse)` (white-on-white, invisible) and the header's
	   dark-surface hover mix (reads as a muddy brown block on a white
	   field). Own color + a plain color swap on hover (no background box,
	   stays visually part of the one pill component). */
	.site-search--inline .icon-btn {
		position: absolute;
		inset-inline-end: var(--wp--preset--spacing--10, 4px);
		top: 50%;
		transform: translateY(-50%);
	}

	/* Specificity note: the header's own `.site-header:not(...) .icon-btn`
	   rule (3 classes) otherwise wins over a plain `.site-search--inline
	   .icon-btn` (2 classes) regardless of source order — confirmed live
	   (icon stayed white-on-white after the first attempt at this fix).
	   Matching that same header-scoped selector shape here. */
	.site-header:not(.site-header--checkout) .site-search--inline .icon-btn {
		color: color-mix(in srgb, var(--wp--preset--color--ink) 60%, var(--wp--preset--color--paper));
	}

	.site-header:not(.site-header--checkout) .site-search--inline .icon-btn:hover,
	.site-header:not(.site-header--checkout) .site-search--inline .icon-btn:focus-visible {
		background: none;
		color: var(--wp--preset--color--brand-gold-700);
	}
}

/* Nav items that only make sense inside the mobile/tablet overlay (category
   shortcuts, account, cart) — desktop already has dedicated icons/space for
   these, so they stay out of the inline row entirely. */
.site-nav .nav-overlay-only {
	display: none;
}

.site-nav .wp-block-navigation__responsive-container.is-menu-open .nav-overlay-only {
	display: flex;
}

/* Align WooCommerce action controls (account/cart) with the icon-btn grid */

.wp-block-woocommerce-customer-account,
.wc-block-mini-cart__button {
	display: inline-flex !important;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	border-radius: var(--wp--custom--radius--sm);
	transition: background-color 150ms ease;
}

.wp-block-woocommerce-customer-account:hover,
.wc-block-mini-cart__button:hover {
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 25%, transparent);
}

.wp-block-woocommerce-customer-account .wc-block-customer-account__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	padding: 0;
}

.wp-block-woocommerce-customer-account .wc-block-customer-account__link svg {
	width: 22px;
	height: 22px;
}

.wc-block-mini-cart__icon {
	width: 22px;
	height: 22px;
}

/* --- Site footer --- */

.site-footer {
	margin-top: var(--wp--preset--spacing--80);
}

.site-footer__main {
	padding-block: var(--wp--preset--spacing--80);
	/* CP-028: same systemic gutter as `.site-main` (CP-018) — this template
	   part's own `layout:constrained` has zero built-in horizontal padding
	   below its 1280px contentSize, so content genuinely touched the
	   viewport edge on mobile. Reuses the identical token, not a new value. */
	padding-inline: var(--wp--preset--spacing--50);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
}

@media (min-width: 1280px) {
	.site-footer__main {
		padding-inline: 0;
	}
}

.site-footer__main a {
	color: color-mix(in srgb, var(--wp--preset--color--ink) 78%, var(--wp--preset--color--paper));
	text-decoration: none;
}

.site-footer__main a:hover,
.site-footer__main a:focus-visible {
	color: var(--wp--preset--color--brand-gold-700);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.site-footer__columns {
	gap: var(--wp--preset--spacing--70);
	row-gap: var(--wp--preset--spacing--60);
}

.footer-heading {
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	/* Full-strength ink (not the muted link tone above) so the heading
	   reads as a label the links sit under, not just another link. */
	color: var(--wp--preset--color--ink);
	margin-block-end: var(--wp--preset--spacing--30);
}

.footer-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--30);
}

.footer-note {
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 70%, var(--wp--preset--color--paper));
}

.footer-legal-id {
	margin-top: var(--wp--preset--spacing--60);
	padding-top: var(--wp--preset--spacing--50);
	border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
}

/* CP-030: the CP-028 disabled input+button pair (then replaced with a
   static "Em breve" pill, since the capability genuinely wasn't built
   yet) is now a real first-party lead-capture form — see footer.html and
   newsletter-signup.js/newsletter-rest.php. */
.footer-newsletter {
	margin-top: var(--wp--preset--spacing--30);
}

.footer-newsletter__row {
	display: flex;
	gap: var(--wp--preset--spacing--20);
	align-items: center;
}

.footer-newsletter__email {
	flex: 1 1 auto;
	min-width: 0;
}

.footer-newsletter__submit {
	flex-shrink: 0;
	white-space: nowrap;
}

@media (min-width: 782px) and (max-width: 1199px) {
	.footer-newsletter__row {
		flex-direction: column;
		align-items: stretch;
	}

	.footer-newsletter__submit {
		width: 100%;
	}
}

.footer-newsletter__consent {
	display: flex;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--20);
	margin-top: var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 75%, var(--wp--preset--color--paper));
	cursor: pointer;
}

.footer-newsletter__consent input[type="checkbox"] {
	flex-shrink: 0;
	width: 18px;
	height: 18px;
	margin-top: 2px;
	accent-color: var(--wp--preset--color--brand-gold-700);
}

.footer-newsletter__message {
	margin: var(--wp--preset--spacing--20) 0 0;
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
}

/* .site-footer__main has no background of its own — it sits on the
   page's normal light surface (only .site-footer__bottom-band below it
   is dark), so these read the same success/error tokens used elsewhere
   on light surfaces (e.g. .notice--success/.notice--error), unmixed. */
.footer-newsletter__message[data-state="success"] {
	color: var(--wp--preset--color--success);
}

.footer-newsletter__message[data-state="error"] {
	color: var(--wp--preset--color--error);
}

.footer-newsletter__submit[disabled] {
	opacity: 0.7;
	cursor: not-allowed;
}

.site-footer__bottom-band {
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--paper);
	padding-block: var(--wp--preset--spacing--40);
	padding-inline: var(--wp--preset--spacing--50);
}

@media (min-width: 1280px) {
	.site-footer__bottom-band {
		padding-inline: 0;
	}
}

.site-footer__bottom {
	align-items: center;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20);
}

.footer-copyright {
	font-size: var(--wp--preset--font-size--sm);
	margin: 0;
	color: color-mix(in srgb, var(--wp--preset--color--paper) 75%, transparent);
}

.site-footer__social {
	list-style: none;
	display: flex;
	gap: var(--wp--preset--spacing--20);
	margin: 0;
	padding: 0;
}

/* CP-030: CP-008.1/CP-028's text-only "Instagram"/"Facebook" pill
   (no official Meta-supplied asset existed in this repo at the time) is
   superseded now that the Product Owner supplied real brand SVGs — see
   assets/icons/SOURCE.md. Same 44px circular hit target and border as the
   old pill, reshaped around an icon instead of text; hover/focus-visible
   keeps the exact same brand-gold-fill treatment the pill already used,
   just applied to the icon's fill color instead of a text label. Links/
   targets are unchanged. */
.footer-social-link {
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--paper) 22%, transparent);
	color: var(--wp--preset--color--paper);
	transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease;
}

.footer-social-link .icon {
	width: 20px;
	height: 20px;
}

.footer-social-link:hover,
.footer-social-link:focus-visible {
	background: var(--wp--preset--color--brand-gold);
	border-color: var(--wp--preset--color--brand-gold);
	color: var(--wp--preset--color--ink);
}

/* --- Responsive: compact header below 782px --- */

@media (max-width: 781px) {
	/* CP-018/CP-021: rebuilt visual hierarchy — hamburger left, logo
	   genuinely centered, search/account/cart right. DOM order is
	   unchanged (logo, nav, search, actions) — only the *visual* position
	   changes, so tab/reading order for assistive tech stays logical.
	   CP-021 fix #1: `.site-header__row` (1 class) never actually won
	   `display:grid` against Gutenberg's own `.is-layout-flex{display:
	   flex}` core rule — equal specificity, source order didn't favor it
	   (confirmed live: computed `display` was still `flex`, this whole
	   grid block was inert). `.site-header .site-header__row` (2 classes)
	   forces the win, same technique already used for `.site-header
	   .site-header__utility` above.
	   CP-021 fix #2: `auto 1fr auto` is NOT genuine viewport centering —
	   the hamburger (~44px) and the search+account+cart group (~144px)
	   are very different widths, so the leftover `1fr` middle column sits
	   centered within the *remaining* space, not the viewport (confirmed
	   live: logo center was ~50px left of true viewport center at
	   390px). `1fr auto 1fr` makes the two flanking tracks equal
	   fractions of the total width regardless of their content's width,
	   which centers the middle (logo) column for real. */
	.site-header .site-header__row {
		display: grid;
		grid-template-columns: 1fr auto 1fr;
		align-items: center;
		gap: var(--wp--preset--spacing--20);
		padding-block: var(--wp--preset--spacing--30);
	}

	.site-logo {
		grid-column: 2;
		grid-row: 1;
		justify-self: center;
	}

	.site-logo img {
		height: 36px;
	}

	.site-nav.wp-block-navigation {
		grid-column: 1;
		grid-row: 1;
		justify-self: start;
		flex-grow: 0;
	}

	.site-header__actions {
		grid-column: 3;
		grid-row: 1;
		justify-self: end;
		gap: 0;
		padding-left: var(--wp--preset--spacing--30);
	}

	.site-search-toggle {
		display: inline-flex;
	}

	/* Collapsed by default on mobile — a real, always-present field would
	   otherwise force its own row (see the 1023px tablet rule below);
	   header-search.js toggles `.is-search-open` on the row to expand it in
	   place instead. Reuses the same form/labels, not a second search UI. */
	.site-search--inline {
		display: none;
	}

	.site-header__row.is-search-open > .site-logo,
	.site-header__row.is-search-open > .site-nav,
	.site-header__row.is-search-open > .site-header__actions {
		display: none;
	}

	.site-header__row.is-search-open > .site-search--inline {
		display: flex;
		grid-column: 1 / -1;
		grid-row: 1;
		align-items: center;
		gap: var(--wp--preset--spacing--20);
	}

	.site-header__row.is-search-open > .site-search--inline .form-input {
		flex: 1;
		min-width: 0;
	}

	.site-footer__main {
		padding-block: var(--wp--preset--spacing--60);
	}

	.site-footer__columns {
		gap: var(--wp--preset--spacing--60);
	}

	.footer-newsletter__row {
		flex-direction: column;
		align-items: stretch;
	}

	.footer-newsletter__submit {
		width: 100%;
	}

	.site-footer__bottom {
		flex-wrap: wrap;
		gap: var(--wp--preset--spacing--30);
	}
}

/* CP-021 Round 4 closure Gate 2: real, confirmed collision at ~768px
   between the logo and "Contactos" — root cause (confirmed live via
   computed styles at every width from 599 to 782px): this theme's nav
   block only actually collapses into the hamburger toggle below 600px
   (`.wp-block-navigation__responsive-container-open` is `display:flex`
   at 599px, `display:none` from 600px up — Gutenberg core's own built-in
   breakpoint for `overlayMenu: "mobile"`, not something this theme's CSS
   controls). The header's compact 3-column grid above assumes the middle
   column always holds a small collapsed hamburger, but from 600-781px it
   actually holds the FULL nav (5 text links) — the flanking `1fr` logo/
   actions columns don't shrink to make room, so the nav's real content
   width overflows straight into the logo's column. Scoped to exactly the
   mismatched sub-range so the untouched hamburger case (≤599px) and the
   already-correct flex/tablet case (≥782px) both keep behaving exactly as
   before — this only repositions the still-full nav to its own grid row,
   nothing else in the block above (search toggle, footer) changes. */
@media (min-width: 600px) and (max-width: 781px) {
	.site-nav.wp-block-navigation {
		grid-column: 1 / -1;
		grid-row: 2;
		justify-self: stretch;
	}

	.site-nav .wp-block-navigation__container {
		justify-content: center;
	}
}

/* Gutenberg keeps the full inline navigation (rather than the hamburger)
   from 600px upward. The injected mobile/tablet language switcher is a
   sibling of that list, so the core list's forced 100% width would push the
   switcher beyond the viewport. Let the two bounded controls wrap as a
   centred group in this exact non-desktop range. */
@media (min-width: 600px) and (max-width: 1023px) {
	.site-nav .wp-block-navigation__responsive-container-content {
		flex-wrap: wrap;
		justify-content: center;
	}

	.site-nav .wp-block-navigation__container {
		width: auto;
		max-width: 100%;
	}

	.site-language-switcher--mobile {
		margin-inline-start: 0;
	}
}

@media (max-width: 390px) {
	.site-header__row {
		padding-inline: var(--wp--preset--spacing--30);
	}
}

/* ==========================================================================
   Home (CP-005)
   ========================================================================== */

.site-main--home {
	/* CP-018: WordPress's own root-level block-gap (--wp--style--block-gap,
	   24px) was applying as margin-top between the header template part and
	   this <main> — a real gap under the header, confirmed live via
	   getComputedStyle, not caused by anything else in this file. */
	margin-top: 0;
	padding-block: 0;
	min-height: 0;
}

/* --- Shared section heading --- */

.section-heading {
	max-width: 640px;
	margin-bottom: var(--wp--preset--spacing--60);
	/* WP's constrained-layout CSS auto-centers any direct section child
	   narrower than the 1280px content size (`margin-inline: auto
	   !important`) — correct for a genuinely centered block, but this
	   heading must share the hero/grid's left edge instead. */
	margin-inline: 0 !important;
}

.section-heading__eyebrow {
	display: flex;
	align-items: center;
	gap: 6px;
	margin: 0 0 var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--wp--preset--color--brand-gold-700);
}

/* Decorative only (aria-hidden) — the eyebrow text already carries the
   meaning, so the glyph inherits the eyebrow's own color via
   currentColor instead of introducing a new token. */
.section-heading__icon {
	flex-shrink: 0;
	width: 14px;
	height: 14px;
}

.section-heading__title {
	margin: 0;
}

.section-heading__lead {
	margin: var(--wp--preset--spacing--20) 0 0;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 70%, var(--wp--preset--color--paper));
}

/* --- Hero campaign carousel (CP-017) --- */

/* The section wrapper itself carries no padding/background any more — the
   full-bleed carousel below provides its own dark band + internal slide
   padding, so an extra `.section` padding-block here would just double up
   the vertical spacing above/below it. */
.hero-section {
	padding-block: 0;
}

.cp-device-defs {
	position: absolute;
	width: 0;
	height: 0;
	overflow: hidden;
}

/* Full-bleed band: the standard scrollbar-safe break-out (percentage-based
   margins, not a raw `100vw` box) — verified safe against this theme's
   layout, which already renders the hero/category/product sections with
   zero horizontal padding below 1280px (confirmed via real
   getBoundingClientRect() measurements, not assumed), so this reproduces
   the previously-approved edge alignment exactly. Continues the header's
   dark surface, same as the CP-016 single-slide hero did. */
.hero-carousel {
	position: relative;
	width: 100vw;
	/* `alignfull` exempts this from the constrained-layout's own
	   `margin-left/right: auto !important` + `max-width:1280px` (otherwise
	   real full-bleed is impossible above ~1280px viewport width — confirmed
	   live). `margin-top:0` cancels WordPress's own block-gap sibling margin
	   (applies between this and the preceding section, confirmed live) —
	   the header/hero vertical gap has two independent causes, this is the
	   second one. */
	margin-block-start: 0;
	margin-inline: calc(50% - 50vw);
	overflow: hidden;
	/* CP-021: the single source of truth for the slide-transition
	   duration — read at runtime by carousel.js's requestAnimationFrame
	   loop (`getComputedStyle(root).getPropertyValue('--hero-carousel-
	   duration')`) and by the copy-entrance `transition-duration` below,
	   so JS motion and CSS motion can never drift into two different
	   hardcoded numbers. 950ms sits inside the approved 900–1000ms band. */
	--hero-carousel-duration: 950ms;
	--hero-copy-duration: var(--hero-carousel-duration);
	--hero-carousel-easing: cubic-bezier(0.22, 0.61, 0.36, 1);
}

.hero-carousel__track {
	display: flex;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
}

.hero-carousel__track::-webkit-scrollbar {
	display: none;
}

.hero-carousel__slide {
	position: relative;
	flex: 0 0 100%;
	/* CP-018: must stay genuinely 100% of the (now truly full-bleed) track
	   width, or the flex-basis/max-width mismatch makes the track's
	   per-slide scroll math land mid-slide (confirmed live: two slides
	   rendered side by side at >1280px viewports). */
	width: 100%;
	scroll-snap-align: start;
	display: flex;
	align-items: center;
	overflow: hidden;
	box-sizing: border-box;
	background: var(--wp--custom--surface--inverse);
	/* Responsive campaign proportion, not one fixed height for every
	   viewport — wide/short on desktop, room for the full-bleed photo. */
	min-height: clamp(420px, 30vw + 200px, 560px);
}

/* CP-021: full-bleed campaign photo — see docs/asset-sources.md's "CP-021
   hero TEMP-ASSET provenance" for the source/rights status of each image.
   `object-position` favors the right edge on desktop, matching every
   source image's own product-on-the-right / negative-space-on-the-left
   composition (see 07-IMAGEGEN-PROVENANCE.md in the creative package). */
.hero-carousel__media {
	position: absolute;
	inset: 0;
}

.hero-carousel__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: right center;
}

/* Guarantees WCAG AA text contrast over the photo regardless of its own
   content — the source images already compose a dark left region for
   copy, this is a safety margin on top of that, not a substitute for it. */
.hero-carousel__scrim {
	position: absolute;
	inset: 0;
	background: linear-gradient(
		100deg,
		color-mix(in srgb, var(--wp--preset--color--ink) 94%, transparent) 0%,
		color-mix(in srgb, var(--wp--preset--color--ink) 85%, transparent) 45%,
		color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent) 70%,
		transparent 92%
	);
}

.hero-carousel__copy {
	position: relative;
	z-index: 2;
	min-width: 0;
	max-width: 36ch;
	padding-inline: max(var(--wp--preset--spacing--30), calc((100% - 1280px) / 2));
	padding-block: var(--wp--preset--spacing--60) var(--wp--preset--spacing--80);
	color: var(--wp--custom--text--on-inverse);
}

.hero-carousel__eyebrow {
	margin: 0 0 var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--wp--preset--color--brand-gold);
}

.hero-carousel__title {
	max-width: 16ch;
	margin: 0 0 var(--wp--preset--spacing--40);
	font-size: clamp(2rem, 1.4rem + 2.6vw, 3.25rem);
	line-height: 1.08;
	font-weight: 700;
	color: var(--wp--custom--text--on-inverse);
}

.hero-carousel__lead {
	max-width: 40ch;
	margin: 0 0 var(--wp--preset--spacing--40);
	font-size: var(--wp--preset--font-size--lg);
	color: var(--wp--custom--text--on-inverse-muted);
}

.hero-carousel__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--30);
}

/* CP-021: copy entrance — opacity/transform only, no bounce/glow. Only the
   active (non-`aria-hidden`) slide's copy animates in; an inactive slide's
   copy sits at its resting (visible) state so it never depends on JS to
   become visible if scripts fail to load. Shares `--hero-carousel-duration`
   with the JS scroll animation so both read as one coordinated move. */
.hero-carousel__slide[aria-hidden="true"] .hero-carousel__eyebrow,
.hero-carousel__slide[aria-hidden="true"] .hero-carousel__title,
.hero-carousel__slide[aria-hidden="true"] .hero-carousel__lead,
.hero-carousel__slide[aria-hidden="true"] .hero-carousel__actions {
	opacity: 0;
	transform: translateY(10px);
}

.hero-carousel__eyebrow,
.hero-carousel__title,
.hero-carousel__lead,
.hero-carousel__actions {
	opacity: 1;
	transform: translateY(0);
	transition: opacity var(--hero-copy-duration) var(--hero-carousel-easing), transform var(--hero-copy-duration) var(--hero-carousel-easing);
}

.hero-carousel__title {
	transition-delay: 60ms;
}

.hero-carousel__lead {
	transition-delay: 110ms;
}

.hero-carousel__actions {
	transition-delay: 160ms;
}

.hero-carousel__controls {
	position: absolute;
	left: 50%;
	bottom: var(--wp--preset--spacing--30);
	transform: translateX(-50%);
	z-index: 2;
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
}

/* CP-021: ~40% smaller container, ~35% closer dots (per the Product
   Owner's dot sketch reference) — achieved by shrinking the dot *button*
   footprint on fine-pointer input while keeping the full 44×44 touch
   target on coarse/touch pointers (UX_SPEC's mobile hit-target floor). */
.hero-carousel__dots {
	display: flex;
	align-items: center;
	gap: 2px;
	padding: 3px 6px;
	border-radius: var(--wp--custom--radius--pill);
	background: color-mix(in srgb, var(--wp--preset--color--ink) 55%, transparent);
	backdrop-filter: blur(6px);
}

.hero-carousel__dot {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	background: none;
	border: none;
	cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
	.hero-carousel__dot {
		width: 26px;
		height: 26px;
	}
}

.hero-carousel__dot::before {
	content: "";
	width: 7px;
	height: 7px;
	border-radius: var(--wp--custom--radius--pill);
	background: color-mix(in srgb, var(--wp--preset--color--paper) 55%, transparent);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	transition: background-color var(--hero-carousel-duration) var(--hero-carousel-easing), width var(--hero-carousel-duration) var(--hero-carousel-easing), border-color var(--hero-carousel-duration) var(--hero-carousel-easing);
}

/* Active state widens into a short capsule instead of just scaling up —
   `border-radius: 999px` on a wider-than-tall box already renders the
   stadium/pill shape on its own once `width` grows past `height`, so the
   width transition alone produces the "emphasis transferred" motion the
   brief asked for, no transform/scale needed. */
.hero-carousel__dot.is-active::before {
	width: 18px;
	background: var(--wp--preset--color--brand-gold);
	border-color: var(--wp--preset--color--brand-gold);
}

.hero-carousel__dot:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold);
	outline-offset: 2px;
	border-radius: 50%;
}

.hero-carousel__playpause {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	background: color-mix(in srgb, var(--wp--preset--color--ink) 55%, transparent);
	border: none;
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--custom--text--on-inverse);
	cursor: pointer;
	backdrop-filter: blur(6px);
}

@media (hover: hover) and (pointer: fine) {
	.hero-carousel__playpause {
		width: 30px;
		height: 30px;
	}
}

.hero-carousel__playpause:hover {
	color: var(--wp--preset--color--brand-gold);
}

.hero-carousel__playpause:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.hero-carousel__eyebrow,
	.hero-carousel__title,
	.hero-carousel__lead,
	.hero-carousel__actions,
	.hero-carousel__slide[aria-hidden="true"] .hero-carousel__eyebrow,
	.hero-carousel__slide[aria-hidden="true"] .hero-carousel__title,
	.hero-carousel__slide[aria-hidden="true"] .hero-carousel__lead,
	.hero-carousel__slide[aria-hidden="true"] .hero-carousel__actions {
		transition: none;
		transform: none;
	}
}

@media (max-width: 781px) {
	.hero-carousel {
		/* CP-031: copy follows an already-active mobile slide promptly; the
		   950ms track motion/autoplay timing remains unchanged. */
		--hero-copy-duration: 280ms;
	}

	.hero-carousel__slide {
		min-height: clamp(480px, 120vw, 640px);
	}

	.hero-carousel__copy {
		max-width: 26ch;
		padding-inline: var(--wp--preset--spacing--30);
		padding-block: var(--wp--preset--spacing--50) var(--wp--preset--spacing--80);
	}

	.hero-carousel__title {
		max-width: none;
		font-size: clamp(1.75rem, 1.3rem + 4vw, 2.5rem);
		transition-delay: 25ms;
	}

	.hero-carousel__lead {
		transition-delay: 50ms;
	}

	.hero-carousel__actions {
		transition-delay: 75ms;
	}
}

/* --- Trust inline list (shared component) --- */
/* Used on light backgrounds — currently the PDP purchase group
   (`.product-summary__trust`). The CP-017 hero carousel no longer uses this
   (kept its own concise copy without a repeated trust list per slide). */

.trust-inline {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 70%, var(--wp--preset--color--paper));
}

.trust-inline li {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
}

.trust-inline li:not(:last-child)::after {
	content: "•";
	color: var(--wp--preset--color--brand-gold-700);
}

/* --- Home scroll-triggered entrance (CP-021) --- */
/* `.reveal-pending` is only ever added by `home-reveal.js`, and only after
   it has confirmed motion is allowed and IntersectionObserver exists — so
   this rule never hides content for a no-JS/JS-failed visitor; the section
   just keeps its normal always-visible styling in that case.
   Transform-only, deliberately no `opacity` change: an automated axe pass
   caught a real defect in an earlier `opacity: 0` version of this rule —
   content still off-screen (not yet revealed) rendered at a contrast ratio
   axe correctly flagged as failing, since a partially-transparent section
   blends its text/background toward the page colour. A slide-into-place
   motion still reads as a real entrance without ever putting content in a
   state that fails contrast if something reaches it before the scroll
   trigger fires (a screen reader's virtual cursor, `Ctrl+F`, etc). */
.reveal-pending {
	transform: translateY(20px);
	transition: transform 500ms ease;
}

.reveal-pending.is-revealed {
	transform: none;
}

/* --- Category discovery --- */

/* CP-021: mobile-first default is the horizontal scroller (see the
   `max-width:781px` rule below for its actual sizing — this base rule only
   exists so the layout doesn't flash as an unstyled block before the media
   queries apply); ≥782px overrides to a real grid. */
.category-grid {
	display: flex;
	gap: var(--wp--preset--spacing--30);
}

/* CP-026: one premium merchandising family across every Home category.
   One light diagonal surface spans the full card; the in-flow media and
   text wrappers stay transparent so they never read as separate panels. */
.category-card {
	position: relative;
	display: flex;
	flex-direction: column;
	box-sizing: border-box;
	min-width: 0;
	border-radius: var(--wp--custom--radius--lg);
	overflow: hidden;
	text-decoration: none;
	background: radial-gradient(140% 120% at 18% 0%, color-mix(in srgb, var(--wp--preset--color--brand-gold) 7%, var(--wp--preset--color--paper)) 0%, var(--wp--preset--color--paper) 60%);
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 8%, transparent);
	box-shadow:
		0 1px 2px color-mix(in srgb, var(--wp--preset--color--ink) 5%, transparent),
		0 16px 32px color-mix(in srgb, var(--wp--preset--color--ink) 8%, transparent);
	transition: transform 200ms ease, box-shadow 200ms ease, border-color 200ms ease;
}

.category-card__media {
	position: relative;
	flex: 0 0 auto;
	aspect-ratio: 1 / 1;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--20) 0;
	overflow: hidden;
	background: transparent;
}

.category-card__media picture {
	display: block;
	width: 100%;
	height: 100%;
}

.category-card__media img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	transition: transform 200ms ease;
}

.category-card__media img {
	filter: drop-shadow(0 14px 22px rgba(0, 0, 0, 0.18));
}

.category-card__body {
	position: relative;
	flex: 1;
	display: flex;
	flex-direction: column;
	justify-content: flex-start;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	background: transparent;
}

.category-card__eyebrow {
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--wp--preset--color--brand-gold-700);
}

.category-card__title {
	margin: var(--wp--preset--spacing--10) 0 0;
	max-width: 18ch;
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 700;
	line-height: 1.25;
}

/* Plain inline flow (not flex) — confirmed live that flex's anonymous
   text-item handling wrapped the label to 2 lines while orphaning the icon
   onto its own 3rd line on the narrower desktop 6-up cards. As a normal
   inline element the icon simply flows with the text like any inline
   icon-after-a-word, wrapping together exactly as expected at any width. */
.category-card__cta {
	display: inline-block;
	margin-top: var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
	color: var(--wp--preset--color--ink);
}

.category-card__cta svg {
	margin-inline-start: var(--wp--preset--spacing--10, 4px);
	vertical-align: -3px;
	transition: transform 200ms ease;
}

/* CP-023B Bloco B1: Product Owner-bounded refinement — translateY -3px to
   -6px max, image scale ~1.00-1.015 max (never the old 1.06 "exaggerated
   deformation"), no size reduction, no layout jump. Depth comes from a
   layered shadow (two shadows: a tight near shadow + a softer diffused
   one) instead of a bigger zoom. */
@media (hover: hover) and (pointer: fine) {
	.category-card:hover,
	.category-card:focus-visible {
		transform: translateY(-5px);
	}

	.category-card:hover .category-card__media img,
	.category-card:focus-visible .category-card__media img {
		transform: scale(1.012) translateY(-1%);
	}

	.category-card:hover .category-card__cta svg,
	.category-card:focus-visible .category-card__cta svg {
		transform: translateX(3px);
	}
}

.category-card:hover,
.category-card:focus-visible {
	border-color: color-mix(in srgb, var(--wp--preset--color--brand-gold-700) 30%, transparent);
	box-shadow:
		0 2px 4px color-mix(in srgb, var(--wp--preset--color--ink) 6%, transparent),
		0 24px 42px color-mix(in srgb, var(--wp--preset--color--ink) 14%, transparent);
}

.category-card:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold);
	outline-offset: 3px;
}

/* The sitewide `*{transition-duration:0.001ms!important}` reset (top of
   this file) already neutralizes this component's own transitions under
   reduced motion — nothing to repeat here. `transform:none` still needs a
   real rule of its own though: without it, hover/focus would still apply
   an instant (unanimated, but real) translateY offset, which this
   project's hero already treats as motion to avoid under reduced motion
   too ("no animated entrance — content appears at rest"). */
@media (prefers-reduced-motion: reduce) {
	.category-card:hover,
	.category-card:focus-visible {
		transform: none;
	}
}

/* --- Featured products --- */
/* CP-017: the old static Home fixture (`.product-grid`/`.product-card`
   article wrapper/placeholder `.device-glyph` icon) is gone — Home now
   renders real WooCommerce ProductCards via `.credphone-shop-grid`/
   `.credphone-featured-grid` (see "Grelha de produtos" below), the same
   markup Shop/Related products already use. Only the shared
   `.product-card__*` sub-component classes (still applied to that native
   markup) remain here. */

.credphone-shop-grid li.wc-block-product {
	position: relative;
	display: flex;
	flex-direction: column;
	padding: var(--wp--preset--spacing--30);
	background: var(--wp--preset--color--paper);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
	border-radius: var(--wp--custom--radius--md);
	list-style: none;
	transition: border-color 150ms ease, box-shadow 150ms ease, transform 150ms ease;
}

.credphone-shop-grid li.wc-block-product:hover {
	border-color: color-mix(in srgb, var(--wp--preset--color--ink) 25%, transparent);
	box-shadow: var(--wp--custom--elevation--raised);
	transform: translateY(-2px);
}

/* Image bleeds to the card edges (minus a hairline gap) instead of sitting
   inside the card's own padding — larger, more product-forward image
   presence (§9/§12 of the CP-016 plan). */
.product-card__media {
	position: relative;
	aspect-ratio: 1 / 1;
	display: flex;
	align-items: center;
	justify-content: center;
	margin: calc(var(--wp--preset--spacing--30) * -1) calc(var(--wp--preset--spacing--30) * -1) var(--wp--preset--spacing--30);
	background: color-mix(in srgb, var(--wp--preset--color--ink) 4%, var(--wp--preset--color--paper));
	border-radius: var(--wp--custom--radius--md) var(--wp--custom--radius--md) 0 0;
}

/* Mobile card image swipe (2026-10-14): `pan-y` tells the browser a
   horizontal touch starting on the image is NOT a page/ancestor scroll
   gesture, so `product-card-swipe.js`'s touchmove can own it instead —
   vertical page scroll is untouched (`pan-y` only reserves the vertical
   axis for native scrolling). Reverted to `auto` on the Home featured
   carousel below, where the whole row's native horizontal scroll-to-
   navigate must keep owning that same gesture (see the featured-grid
   override + `docs/` note on this root cause). */
.credphone-shop-grid .product-card__media {
	touch-action: pan-y;
}

/* CP-012: desktop-pointer-only secondary-image hover (see the
   `render_block_woocommerce/product-image` filter in credphone-core.php).
   Absent on touch — `hover`/`focus-within` never persist on a tapped card,
   so a phone never "shows" the wrong image after a tap. */
.product-card__media-hover {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: contain;
	opacity: 0;
	transition: opacity 200ms ease;
	pointer-events: none;
}

/* Ghosting fix (found live 2026-09-30, e.g. Samsung Galaxy Z Fold 8): the
   hover overlay is a real product photo, not a flat-color swatch — most of
   ours are transparent-background PNGs from the standardization pipeline
   (`lib/image-standardize.mjs`). With only the overlay animating in, its
   transparent regions let the PRIMARY image show through underneath at
   full opacity — two photos visible at once instead of a clean swap. A
   real crossfade needs BOTH layers to transition: primary fades OUT
   exactly as the overlay fades IN, so at 100% hover nothing is left
   painted behind the overlay's transparent edges except the card's own
   near-white stage background (`.product-card__media`'s own
   `background`), which every standardized photo is already designed to
   sit on. `:has(+ .product-card__media-hover)` scopes the fade to cards
   that actually got a hover overlay injected — a card with no gallery
   image never gets the sibling, so its primary image is untouched. */
.product-card__media img[data-testid="product-image"] {
	transition: opacity 200ms ease;
}

/* Bug real reportado pelo PO (2026-10-13): o crossfade estava ligado ao
   CARTÃO INTEIRO (`li.wc-block-product:hover`) — clicar num swatch mantém o
   rato dentro do `<li>` (o controlo fica abaixo da imagem), então o cartão
   continua `:hover` e a 2ª imagem da cor recém-selecionada aparecia de
   imediato em vez de só ao passar o rato na imagem. `.product-card__media`
   é exatamente a `<div>` da imagem (className do bloco `woocommerce/
   product-image`) — nunca contém swatches/preço/CTA, que são irmãos no
   DOM — por isso ancorar aqui é suficiente e correto. */
@media (hover: hover) and (pointer: fine) {
	.credphone-shop-grid .product-card__media:hover .product-card__media-hover,
	.credphone-shop-grid .product-card__media:focus-within .product-card__media-hover {
		opacity: 1;
	}

	.credphone-shop-grid .product-card__media:hover img[data-testid="product-image"]:has(+ .product-card__media-hover),
	.credphone-shop-grid .product-card__media:focus-within img[data-testid="product-image"]:has(+ .product-card__media-hover) {
		opacity: 0;
	}
}

/* Mobile card image swipe (2026-10-14): same two <img> elements, same
   crossfade, as the desktop `:hover` block above — `product-card-swipe.js`
   toggles this class instead of relying on `:hover` (touch has none).
   Reuses the exact opacity/transition already declared on both images;
   no new animation. Not gated to `.credphone-shop-grid` — the class is
   only ever added by touch gesture JS, which already refuses to attach
   inside `.credphone-featured-grid` (the carousel keeps native swipe
   there), so there is no touch surface where this could fire unwanted. */
.product-card__media.is-swiped .product-card__media-hover {
	opacity: 1;
}

.product-card__media.is-swiped img[data-testid="product-image"]:has(+ .product-card__media-hover) {
	opacity: 0;
}

.product-card__wishlist {
	position: absolute;
	top: var(--wp--preset--spacing--30);
	right: var(--wp--preset--spacing--30);
	background: color-mix(in srgb, var(--wp--preset--color--paper) 85%, transparent);
}

.product-card__financing {
	align-self: flex-start;
	margin-bottom: var(--wp--preset--spacing--30);
}

.product-card__name {
	margin: 0 0 var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--base);
	font-weight: 600;
}

.product-card .price {
	margin-bottom: var(--wp--preset--spacing--40);
}

/* CP-038: one shared, variation-backed colour selector for Product
   Collection cards (Home, Shop, Category and Related Products). The catalog
   audit found no authoritative hex/swatch metadata, so the 14px visual chip
   is intentionally neutral instead of guessing a colour. Its 28px button,
   real colour name (aria-label/title) and pressed ring carry the interaction. */
.product-card__color-swatches {
	display: flex;
	align-items: center;
	gap: 4px;
	min-height: 32px;
	margin: 0 0 var(--wp--preset--spacing--20);
	overflow-x: auto;
	overflow-y: hidden;
	scrollbar-width: none;
}

.product-card__color-swatches::-webkit-scrollbar {
	display: none;
}

.product-card__color-swatch,
.product-card__color-more {
	box-sizing: border-box;
	flex: 0 0 28px;
	display: inline-grid;
	place-items: center;
	width: 28px;
	height: 28px;
	min-width: 28px;
	padding: 0;
	background: transparent;
	border: 1px solid transparent;
	border-radius: 50%;
	color: var(--wp--preset--color--ink);
	font: inherit;
	font-size: 11px;
	font-weight: 700;
	line-height: 1;
	cursor: pointer;
}

.product-card__color-swatch > span {
	display: block;
	width: 14px;
	height: 14px;
	background: var(--credphone-swatch-color, color-mix(in srgb, var(--wp--preset--color--ink) 10%, var(--wp--preset--color--paper)));
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 42%, transparent);
	border-radius: 50%;
	box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--wp--preset--color--paper) 55%, transparent);
}

.product-card__color-swatch[data-credphone-swatch-pattern="camo"] > span {
	background: repeating-linear-gradient(
		135deg,
		#5b5a45 0 5px,
		#43492f 5px 10px,
		#2c2e22 10px 14px,
		#6b6a52 14px 19px
	);
}

.product-card__color-swatch:hover,
.product-card__color-more:hover {
	background: color-mix(in srgb, var(--wp--preset--color--ink) 5%, transparent);
}

.product-card__color-swatch.is-selected,
.product-card__color-swatch[aria-pressed="true"] {
	border-color: var(--wp--preset--color--ink);
	box-shadow: 0 0 0 2px var(--wp--preset--color--paper), 0 0 0 3px color-mix(in srgb, var(--wp--preset--color--ink) 58%, transparent);
}

.product-card__color-swatch:focus-visible,
.product-card__color-more:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 2px;
}

.product-card__color-swatch[hidden] {
	display: none;
}

.product-card__color-more {
	border-color: color-mix(in srgb, var(--wp--preset--color--ink) 20%, transparent);
	border-radius: var(--wp--custom--radius--pill);
}

/* A chosen variation image must remain visible instead of being covered by
   the parent's generic secondary-gallery hover image. */
.wc-block-product[data-credphone-color-image-selected="true"] .product-card__media-hover {
	display: none;
}

/* ...and since the overlay is suppressed (display:none, so `:has(+
   .product-card__media-hover)` above still matches it structurally), the
   primary image's crossfade-out must be suppressed too — otherwise
   hovering a product with an explicitly-selected color fades the visible
   photo to nothing with no overlay behind it to replace it. Same
   selector shape/specificity as the fade-out rule, placed after it, so
   source order decides the tie. */
.credphone-shop-grid li.wc-block-product[data-credphone-color-image-selected="true"] .product-card__media:hover img[data-testid="product-image"],
.credphone-shop-grid li.wc-block-product[data-credphone-color-image-selected="true"] .product-card__media:focus-within img[data-testid="product-image"] {
	opacity: 1;
}

/* --- Positioning/UX pass: card CTA hierarchy — one row, "[ small cart
   control ] [ Comprar agora ]" (approved brief). CSS Grid instead of the
   previous column stack so the control (icon button, or the "− qty +"
   stepper it turns into) and "Comprar agora" always sit side by side —
   never a second component stacked below the primary CTA. The control
   column has a fixed width so switching between its two states never
   changes "Comprar agora"'s available width (brief: "sem layout shift").
   Injected by credphone-core via render_block_woocommerce/product-button. --- */

/* Three classes needed to beat WooCommerce's own per-block inline style
   (`.wp-block-button.wc-block-components-product-button { display: flex }`,
   printed in <head> by block supports, specificity 0,0,2,0) — confirmed
   live: a two-class selector here tied its specificity and lost on source
   order, leaving `display: flex` in charge and "Comprar agora" stacked
   under the cart control again instead of beside it. */
.credphone-shop-grid .wc-block-components-product-button.product-card__cta {
	margin-top: auto;
	width: 100%;
	display: grid;
	grid-template-columns: max-content 1fr;
	gap: var(--wp--preset--spacing--20);
}

.product-card__buy-now {
	grid-column: 2;
	grid-row: 1;
	width: 100%;
	justify-content: center;
	/* Visual micro-polish pass: the base `.btn` horizontal padding (24px a
	   side) left too little room for "Comprar agora" on one line in the
	   narrowest real layout confirmed on staging (a 4-column category page
	   with the filters sidebar open, ~151px available for this button) —
	   PO-approved fallback per brief §7 ("adaptar tipografia/padding antes
	   de aceitar quebra"). Vertical padding/min-height untouched. Scoped to
	   `.product-card__buy-now` only — the PDP's own, much wider buy-now
	   button is unaffected. */
	padding-inline: 12px;
}

/* Visual micro-polish pass: the variable-product card's "Comprar agora"
   reuses WooCommerce's own `wc-block-components-product-button__button`
   class (it started life as the "Ver opções" link) — a WooCommerce inline
   block style (`.wp-block-button.wc-block-components-product-button
   .wc-block-components-product-button__button { line-height: inherit }`,
   specificity 0,0,2,0) tied and beat this theme's own `.btn { line-height:
   1.2 }` by source order, inheriting a 1.6 line-height from further up the
   tree instead. Confirmed live: 17px×1.6 vs. the simple-product card's
   correct 17px×1.2 was the reason "Comprar agora" wrapped onto visibly
   more lines on the variable-product card specifically, at the exact same
   button width/font-size. Three classes to safely beat that 0,0,2,0 rule
   regardless of source order (same pattern as the icon-button fixes
   above). */
.credphone-shop-grid .wc-block-components-product-button__button.product-card__buy-now {
	line-height: 1.2;
	/* Same padding fix as the general rule above, restated at higher
	   specificity — the variable-product card's "Comprar agora" carries
	   the native class too, so it needs the same 0,0,3,0 override to
	   actually beat `.btn, .wc-block-components-product-button__button`
	   (0,0,2,0) for padding, not just line-height. */
	padding-inline: 12px;
}

.product-card__add-to-cart {
	grid-column: 1;
	grid-row: 1;
}

/* CP-029: one fixed-size circle for every state — not-in-cart, in-cart, or
   hovered — the "− qty +" stepper that used to share this grid cell is
   gone entirely (brief §5: no micro-stepper, no width change between
   states). Neutral, secondary look, never the brand-gold CTA fill. This
   general rule is sufficient for the variable-product card's own plain
   `<button class="icon-btn product-card__add-to-cart">` (no competing
   classes there), but NOT for the simple-product card's button (see the
   3-class rule right below) — it reuses WooCommerce's own
   `wc-block-components-product-button__button`/`wp-block-button__link`
   classes, which carry several same-or-higher-specificity declarations
   (background, border-style, padding, width) that this single class alone
   cannot beat; those get the identical values repeated there instead of
	 relying on this rule to cascade through. `position: relative` anchors
   the three absolutely-positioned bag/check/eye icons below. */
.product-card__add-to-cart {
	position: relative;
	width: 44px;
	min-width: 44px;
	height: 44px;
	align-self: center;
	padding: 0;
	gap: 0;
	background: var(--wp--preset--color--paper);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 18%, transparent);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--ink);
	overflow: visible;
}

/* Three classes to beat, property by property, everything WooCommerce's
   own styles put on this exact button (all confirmed live, each one
   individually silently winning before it was listed here explicitly):
   `.btn, .wc-block-components-product-button__button` (0,0,2,0) supplies
   the brand-gold fill and ~24px horizontal padding; `.wp-block-button.
   wc-block-components-product-button .wc-block-components-product-
   button__button` (0,0,2,0) zeroes border-style; `.wp-block-button.
   wc-block-components-product-button .wp-block-button__link` (0,0,2,0)
   sets width:auto. This selector's three classes (0,0,3,0) beat all of
   them at once, so every property that matters is restated here rather
   than left to partially cascade from the general rule above. */
.credphone-shop-grid .wc-block-components-product-button__button.product-card__add-to-cart {
	position: relative;
	width: 44px;
	min-width: 44px;
	height: 44px;
	align-self: center;
	padding: 0;
	font-size: 0;
	background: var(--wp--preset--color--paper);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 18%, transparent);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--ink);
	overflow: visible;
}

/* Subtle resting-state tell that this exact selection is already in the
   cart (brief §6: "pode usar uma diferença visual muito subtil") — never a
   size/width change, only a slightly warmer border + icon tint. Simple
   products only — a variable parent's trigger never carries this
   attribute (brief §11). `.credphone-shop-grid` ancestor is required here
   (not just cosmetic) — confirmed live that without it, this 2-selector
   rule (0,0,2,0) loses the border-color property outright to the 3-class
   rule above (0,0,3,0) beating WooCommerce's own native button styles;
   adding the same ancestor here ties that specificity and wins on source
   order. */
.credphone-shop-grid .product-card__cart-toggle[data-credphone-in-cart="1"] {
	border-color: color-mix(in srgb, var(--wp--preset--color--brand-gold-700) 45%, transparent);
	color: var(--wp--preset--color--brand-gold-700);
}

@media (hover: hover) and (pointer: fine) {
	/* The control is a secondary toggle, not a CTA — it keeps the same
	   quiet gold-tint hover every other neutral icon button on the site
	   already uses (`.icon-btn:hover`), never the lift+shadow "premium
	   button" hover meant for `.btn`/the native Woo CTA fill. `.credphone-
	   shop-grid` qualifier bumps specificity above the competing
	   `.credphone-shop-grid .wc-block-components-product-button__button:hover`
	   rule above (same 0,0,2,0 tier otherwise — not worth relying on
	   source order after already being bitten by that once this pass). */
	.credphone-shop-grid .product-card__add-to-cart:hover {
		background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 18%, var(--wp--preset--color--paper));
		transform: none;
		box-shadow: none;
	}
}

/* CP-029B: lightweight first-party action hint. The accessible name stays
   on aria-label; this pseudo-element is visual-only, takes no layout space,
   does not track the pointer and appears after a short 120ms intent delay.
   `data-tooltip` is updated with the same confirmed cart state as the
   action, so it never describes an add while the control opens the Cart. */
.product-card__add-to-cart[data-tooltip]::after {
	content: attr(data-tooltip);
	position: absolute;
	left: 50%;
	bottom: calc(100% + 8px);
	z-index: 30;
	width: max-content;
	max-width: min(190px, 70vw);
	padding: 6px 9px;
	background: var(--wp--preset--color--ink);
	border-radius: var(--wp--custom--radius--sm);
	box-shadow: 0 4px 12px color-mix(in srgb, var(--wp--preset--color--ink) 20%, transparent);
	color: var(--wp--preset--color--paper);
	font-family: inherit;
	font-size: 12px;
	font-weight: 600;
	line-height: 1.2;
	text-align: center;
	white-space: nowrap;
	pointer-events: none;
	opacity: 0;
	visibility: hidden;
	transform: translate(-50%, 4px);
	transition: opacity 90ms ease, transform 90ms ease, visibility 0s linear 90ms;
}

.product-card__add-to-cart[data-tooltip]:focus-visible::after {
	opacity: 1;
	visibility: visible;
	transform: translate(-50%, 0);
	transition-delay: 120ms;
}

@media (any-hover: hover) {
	.product-card__add-to-cart[data-tooltip]:hover::after {
		opacity: 1;
		visibility: visible;
		transform: translate(-50%, 0);
		transition-delay: 120ms;
	}
}

/* The featured rail clips horizontally by design. Its first circle sits
   close enough to that edge that a centred long tooltip could be trimmed;
   align only that one inward while every other tooltip remains centred. */
.credphone-featured-grid li.wc-block-product:first-child .product-card__add-to-cart[data-tooltip]::after {
	left: 0;
	transform: translateY(4px);
}

.credphone-featured-grid li.wc-block-product:first-child .product-card__add-to-cart[data-tooltip]:focus-visible::after {
	transform: translateY(0);
}

@media (any-hover: hover) {
	.credphone-featured-grid li.wc-block-product:first-child .product-card__add-to-cart[data-tooltip]:hover::after {
		transform: translateY(0);
	}
}

/* At phone widths the first card's circle is close enough to the viewport
   edge that a centred pt-PT label loses a few pixels. Keyboard focus can
   still expose the hint on touch-sized layouts, so anchor it inward there. */
@media (max-width: 480px) {
	.product-card__add-to-cart[data-tooltip]::after {
		left: 0;
		transform: translateY(4px);
	}

	.product-card__add-to-cart[data-tooltip]:focus-visible::after {
		transform: translateY(0);
	}
}

/* A tap must never leave a visual hint stuck over the card. The control's
   aria-label remains the complete accessible name on touch devices. */
@media (hover: none) and (pointer: coarse) {
	.product-card__add-to-cart[data-tooltip]::after {
		display: none;
	}
}

.product-card__add-to-cart[hidden] {
	display: none;
}

/* Bag/check/eye crossfade (CP-031) — all icons are always rendered,
   absolutely centered on top of each other; only `opacity` changes, using this
   theme's `motion.fast` token (160ms, inside the approved 150–200ms band).
   CHECK is the in-cart resting state. The eye only becomes visible as a
   hover/focus state on a control that is
   ALREADY `data-credphone-in-cart="1"` — a not-yet-added product's
   hover/focus never shows it, matching brief §7's deterministic
   "NOT IN CART: click = add one / IN CART: hover→eye, click = open Cart". */
.product-card__cart-icon {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	flex-shrink: 0;
	transition: opacity var(--wp--custom--motion--fast) ease;
}

.product-card__cart-icon--check,
.product-card__cart-icon--eye {
	opacity: 0;
}

.product-card__cart-toggle[data-credphone-in-cart="1"] .product-card__cart-icon--bag {
	opacity: 0;
}

.product-card__cart-toggle[data-credphone-in-cart="1"] .product-card__cart-icon--check {
	opacity: 1;
}

.product-card__cart-toggle[data-credphone-in-cart="1"]:focus-visible .product-card__cart-icon--check {
	opacity: 0;
}

.product-card__cart-toggle[data-credphone-in-cart="1"]:focus-visible .product-card__cart-icon--eye {
	opacity: 1;
}

@media (any-hover: hover) {
	.product-card__cart-toggle[data-credphone-in-cart="1"]:hover .product-card__cart-icon--check {
		opacity: 0;
	}

	.product-card__cart-toggle[data-credphone-in-cart="1"]:hover .product-card__cart-icon--eye {
		opacity: 1;
	}
}

/* "Remover" (brief §9) — small, muted, underlined text link between the
   product name and price on a card whose exact selection is already in
   the cart. Injected by credphone-core via
   render_block_woocommerce/product-price, starts `[hidden]` (no reserved
   empty space) until cart-sync.js reveals it for a genuinely in-cart
   selection; simple products only (see the PHP filter's variation_id/
   is_type('simple') guards — never rendered at all for a variable
   parent). */
.product-card__remove-line {
	display: inline-block;
	align-self: flex-start;
	margin: 0 0 var(--wp--preset--spacing--20);
	padding: 0;
	background: none;
	border: none;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 60%, var(--wp--preset--color--paper));
	text-decoration: underline;
	text-underline-offset: 2px;
	cursor: pointer;
}

.product-card__remove-line:hover,
.product-card__remove-line:focus-visible {
	color: var(--wp--preset--color--error);
}

.product-card__remove-line[hidden] {
	display: none;
}

/* CP-019: WooCommerce's own legacy `.ajax_add_to_cart` JS (independent of
   the Interactivity API bindings above — no `data-wp-bind` on it, plain
   jQuery-appended markup) inserts this "Ver carrinho" link as a sibling of
   the button after every add. The bag/eye control fully replaces it as the
   in-cart affordance, so it never gets a visible state here. */
.credphone-shop-grid .added_to_cart.wc_forward {
	display: none;
}

/* "Ver carrinho" nativo do Woo — promovido a ação clara depois do 1º add. */
.product-card__cta .added_to_cart.wc_forward {
	align-self: flex-start;
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	text-decoration: underline;
	text-underline-offset: 3px;
	color: var(--wp--preset--color--ink);
}

.product-card__cta .added_to_cart.wc_forward:hover {
	color: var(--wp--preset--color--brand-gold-700);
}

/* --- Financing banner --- */

.financing-banner {
	padding: var(--wp--preset--spacing--70) var(--wp--preset--spacing--60);
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--paper);
	border-radius: var(--wp--custom--radius--lg);
}

.financing-banner__copy {
	max-width: 56ch;
}

.financing-banner__eyebrow {
	color: var(--wp--preset--color--brand-gold);
}

.financing-banner__title {
	margin: 0 0 var(--wp--preset--spacing--30);
	color: var(--wp--preset--color--paper);
}

.financing-banner__lead {
	margin: 0 0 var(--wp--preset--spacing--50);
	color: color-mix(in srgb, var(--wp--preset--color--paper) 80%, transparent);
}

/* --- Trust / benefits --- */

.benefits-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--wp--preset--spacing--50);
}

.benefit-item {
	padding-top: var(--wp--preset--spacing--30);
	border-top: 2px solid var(--wp--preset--color--brand-gold);
}

.benefit-item__title {
	margin: 0 0 var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--base);
}

.benefit-item__text {
	margin: 0;
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 70%, var(--wp--preset--color--paper));
}

/* --- Brand / product discovery showcase --- */
/* CP-021 (redesign): was two flat-color text-only panels (no photo, no
   real link target — both pointed at generic `/shop/`). Rebuilt as real
   editorial panels using the same media/body zone language as the
   category cards just above, so the two components read as one coherent
   family rather than two different patterns on the same page. */

.showcase-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--wp--preset--spacing--40);
}

.showcase-panel {
	position: relative;
	display: flex;
	flex-direction: column;
	box-sizing: border-box;
	border-radius: var(--wp--custom--radius--lg);
	overflow: hidden;
	text-decoration: none;
	transition: transform 200ms ease, box-shadow 200ms ease;
}

.showcase-panel--ink {
	background: linear-gradient(165deg, var(--wp--custom--surface--inverse), color-mix(in srgb, var(--wp--custom--surface--inverse) 80%, black) 65%, color-mix(in srgb, var(--wp--preset--color--brand-gold) 10%, black));
	color: var(--wp--custom--text--on-inverse);
}

.showcase-panel--gold {
	background: linear-gradient(165deg, color-mix(in srgb, var(--wp--preset--color--brand-gold) 26%, var(--wp--preset--color--paper)), color-mix(in srgb, var(--wp--preset--color--brand-gold) 6%, var(--wp--preset--color--paper)) 60%, var(--wp--preset--color--paper));
	color: var(--wp--preset--color--ink);
	border: var(--wp--custom--elevation--border);
}

.showcase-panel__media {
	position: relative;
	flex: 0 0 auto;
	aspect-ratio: 16 / 10;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40) var(--wp--preset--spacing--20);
	overflow: hidden;
}

.showcase-panel--ink .showcase-panel__media {
	background: radial-gradient(120% 90% at 50% 30%, color-mix(in srgb, var(--wp--preset--color--brand-gold) 16%, transparent), transparent 72%);
}

.showcase-panel--gold .showcase-panel__media {
	background: radial-gradient(120% 90% at 50% 30%, color-mix(in srgb, var(--wp--preset--color--brand-gold) 12%, transparent), transparent 72%);
}

.showcase-panel__media picture {
	display: block;
	width: 100%;
	height: 100%;
}

.showcase-panel__media img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	transition: transform 200ms ease;
}

.showcase-panel--ink .showcase-panel__media img {
	filter: drop-shadow(0 18px 28px rgba(0, 0, 0, 0.5));
}

.showcase-panel--gold .showcase-panel__media img {
	filter: drop-shadow(0 18px 28px rgba(0, 0, 0, 0.18));
}

.showcase-panel__body {
	position: relative;
	flex: 1;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--50) var(--wp--preset--spacing--60);
}

.showcase-panel__eyebrow {
	margin: 0;
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	opacity: 0.85;
}

.showcase-panel--ink .showcase-panel__eyebrow {
	color: var(--wp--preset--color--brand-gold);
}

.showcase-panel--gold .showcase-panel__eyebrow {
	color: var(--wp--preset--color--brand-gold-700);
}

.showcase-panel__title {
	margin: var(--wp--preset--spacing--10) 0 0;
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 700;
	line-height: 1.2;
	color: inherit;
}

.showcase-panel__link {
	display: inline-block;
	margin-top: var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
}

.showcase-panel--ink .showcase-panel__link {
	color: var(--wp--preset--color--brand-gold);
}

.showcase-panel--gold .showcase-panel__link {
	color: var(--wp--preset--color--brand-gold-700);
}

.showcase-panel__link svg {
	margin-inline-start: var(--wp--preset--spacing--10, 4px);
	vertical-align: -3px;
	transition: transform 200ms ease;
}

@media (hover: hover) and (pointer: fine) {
	.showcase-panel:hover,
	.showcase-panel:focus-visible {
		transform: translateY(-4px);
	}

	.showcase-panel:hover .showcase-panel__media img,
	.showcase-panel:focus-visible .showcase-panel__media img {
		transform: scale(1.06) translateY(-2%);
	}

	.showcase-panel:hover .showcase-panel__link svg,
	.showcase-panel:focus-visible .showcase-panel__link svg {
		transform: translateX(3px);
	}
}

.showcase-panel--ink:hover,
.showcase-panel--ink:focus-visible {
	box-shadow: 0 16px 32px color-mix(in srgb, var(--wp--preset--color--brand-gold) 22%, transparent);
}

.showcase-panel--gold:hover,
.showcase-panel--gold:focus-visible {
	box-shadow: 0 16px 32px color-mix(in srgb, var(--wp--preset--color--ink) 14%, transparent);
}

.showcase-panel:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold);
	outline-offset: 3px;
}

/* Same sitewide reduced-motion reset covers transition-duration; only the
   instant (unanimated) transform offset needs its own opt-out, matching
   `.category-card`'s identical reduced-motion rule above. */
@media (prefers-reduced-motion: reduce) {
	.showcase-panel:hover,
	.showcase-panel:focus-visible {
		transform: none;
	}
}

@media (min-width: 1024px) {
	.showcase-panel {
		flex-direction: row;
	}

	.showcase-panel__media {
		flex: 0 0 46%;
		aspect-ratio: auto;
	}

	.showcase-panel__body {
		padding-inline-start: var(--wp--preset--spacing--40);
	}
}

/* --- Support / conversion CTA --- */

.support-cta__box {
	max-width: 640px;
	/* This was the one visually-centered island on an otherwise consistently
	   left-aligned Home page (hero/category/featured/benefits/showcase all
	   share the same left edge) — flush it left like every other section
	   instead of floating it in the middle of the row. */
	margin-inline: 0 !important;
	padding: var(--wp--preset--spacing--70) var(--wp--preset--spacing--50);
	text-align: left;
	background: var(--wp--preset--color--paper);
	border: var(--wp--custom--elevation--border);
	border-radius: var(--wp--custom--radius--lg);
}

.support-cta__title {
	margin: 0 0 var(--wp--preset--spacing--30);
}

.support-cta__lead {
	margin: 0 0 var(--wp--preset--spacing--50);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 70%, var(--wp--preset--color--paper));
}

.support-cta__actions {
	display: flex;
	align-items: center;
	justify-content: flex-start;
	gap: var(--wp--preset--spacing--30);
}

/* --- Home responsive --- */

@media (min-width: 782px) {
	/* CP-018: was a literal repeat(4, 1fr) — since .benefit-item--financing
	   is sitewide CSS-hidden (pending approved financing rates), that left a
	   permanently empty reserved 4th track (same root-cause class as the
	   CP-017 auto-fill grid bug). auto-fit collapses the unused track and
	   lets the 3 real cards fill the row properly. */
	.benefits-grid {
		grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	}
}

@media (min-width: 1024px) {
	/* Gate 5: 5 balanced columns (the Acessórios card was removed from the
	   Home strip — category/nav/filters/URL are untouched, see
	   TASKS.md). Grid only activates here — mobile AND tablet stay on the
	   horizontal scroller below (max-width: 1023px) so 5 items never has
	   to fake-balance an uneven 3-then-2 grid row. */
	.category-grid {
		display: grid;
		grid-template-columns: repeat(5, 1fr);
		overflow-x: visible;
		padding-inline: 0;
		margin-inline: 0;
	}

	.category-card {
		flex: initial;
		scroll-snap-align: none;
	}

	/* The narrowest CTA labels ("Explorar computadores") wrap the arrow
	   onto its own line at 14px in a ~204px 5-up card (confirmed live) —
	   13px keeps every label on one line at this breakpoint. */
	.category-card__cta {
		font-size: 0.8125rem;
	}
}

@media (max-width: 781px) {
	.showcase-grid {
		grid-template-columns: 1fr;
	}

	.support-cta__actions {
		flex-direction: column;
	}

	.support-cta__actions .btn {
		width: 100%;
	}
}

/* CP-023B Bloco B2: mobile "stacked deck" — replaces the CP-021 horizontal
   scroller below 1024px (≥1024px keeps its own 5-column grid untouched,
   see the (min-width: 1024px) rules above). Front card at rest, 2 back
   cards peeking (small offset + subtle rotation + near-full scale, per
   the Product Owner's spec) — `[data-stack-order]` is written by
   category-card-stack.js; without JS every card keeps its server-rendered
   DOM order (0,1,2,3,4) so the deck still renders a sensible static stack
   rather than an empty container. `--category-stack-height` is measured
   live by that same script (card copy length varies per category, so a
   guessed fixed height would either clip a longer title or leave dead
   space under a shorter one). */
@media (max-width: 1023px) {
	.category-grid {
		position: relative;
		display: block;
		height: var(--category-stack-height, 420px);
		padding-inline: var(--wp--preset--spacing--50);
		margin-inline: 0;
		touch-action: pan-y;
	}

	.category-card {
		position: absolute;
		inset: 0 0 auto;
		width: auto;
		flex: initial;
		transition: transform 320ms var(--wp--custom--easing--standard, ease), opacity 320ms ease;
	}

	.category-card[data-stack-order="0"] {
		z-index: 4;
		transform: none;
		opacity: 1;
	}

	.category-card[data-stack-order="1"] {
		z-index: 3;
		transform: translateY(14px) rotate(-2deg) scale(0.96);
		opacity: 1;
		pointer-events: none;
	}

	.category-card[data-stack-order="2"] {
		z-index: 2;
		transform: translateY(26px) rotate(2deg) scale(0.92);
		opacity: 1;
		pointer-events: none;
	}

	.category-card[data-stack-order="3"] {
		z-index: 1;
		transform: translateY(30px) scale(0.88);
		opacity: 0;
		pointer-events: none;
	}

	/* An in-progress drag/exit sets its own inline transform every frame
	   (see category-card-stack.js) — the attribute-driven transition above
	   would otherwise fight it for the same property. */
	.category-card[data-dragging="true"] {
		transition: none;
	}

	/* The desktop-only hover lift (Bloco B1, `(hover: hover) and
	   (pointer: fine)`) is about input capability, not viewport width — a
	   desktop browser narrowed to this breakpoint still matches it. Cancel
	   it here: the card's `transform` is the stack-position mechanism
	   itself at this breakpoint, and a translateY hover offset would fight
	   the [data-stack-order] rules above for the same property. */
	.category-card[data-stack-order="0"]:hover,
	.category-card[data-stack-order="0"]:focus-visible {
		transform: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.category-card[data-dragging="true"] {
		transition: none;
	}
}

/* Prev/next + dots + a visually-hidden live region — the gesture's
   required keyboard/button equivalent (Bloco B2). Hidden by default in
   markup ([hidden], removed by category-card-stack.js once it confirms
   the stack it controls is real) and CSS-gated to the same <1024px
   breakpoint as the stack itself, so it can never show stranded on the
   desktop 5-column grid even if JS runs before that breakpoint applies. */
.category-stack-nav {
	display: none;
}

@media (max-width: 1023px) {
	.category-stack-nav:not([hidden]) {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: var(--wp--preset--spacing--30);
		margin-block-start: var(--wp--preset--spacing--30);
	}
}

.category-stack-nav__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: var(--wp--custom--elevation--border);
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	cursor: pointer;
	transition: background-color 150ms ease, transform 150ms ease;
}

.category-stack-nav__btn:hover,
.category-stack-nav__btn:focus-visible {
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 14%, var(--wp--preset--color--paper));
}

.category-stack-nav__btn:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold);
	outline-offset: 2px;
}

.category-stack-nav__btn:active {
	transform: scale(0.94);
}

.category-stack-nav__dots {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--10, 6px);
}

.category-stack-nav__dot {
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: color-mix(in srgb, var(--wp--preset--color--ink) 22%, transparent);
	transition: background-color 150ms ease, transform 150ms ease;
}

.category-stack-nav__dot.is-active {
	background: var(--wp--preset--color--brand-gold-700, var(--wp--preset--color--brand-gold));
	transform: scale(1.3);
}

@media (prefers-reduced-motion: reduce) {
	.category-stack-nav__btn,
	.category-stack-nav__dot {
		transition: none;
	}
}

@media (max-width: 390px) {
	.category-stack-nav {
		margin-block-start: var(--wp--preset--spacing--20);
	}
}

@media (max-width: 390px) {
	.benefits-grid {
		grid-template-columns: 1fr;
	}
}

/* =========================================================
   Shop / listagem de produtos (CP-006)
   Reutiliza os componentes/tokens já existentes acima
   (.badge, .btn, .notice, .product-card*, .price). Os
   seletores contra classes do WooCommerce foram confirmados
   no HTML real renderizado pelo wp-env (WooCommerce 11.0.1),
   não adivinhados.
   ========================================================= */

.shop-breadcrumbs {
	margin-bottom: var(--wp--preset--spacing--30);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
}

.shop-breadcrumbs a {
	color: inherit;
}

.shop-title {
	margin-bottom: var(--wp--preset--spacing--20);
}

.shop-description {
	max-width: 65ch;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 75%, var(--wp--preset--color--paper));
}

.shop-description:empty {
	display: none;
}

/* --- Navegação de categorias (provisória) --- */

.shop-category-nav {
	display: flex;
	flex-wrap: nowrap;
	align-items: stretch;
	gap: var(--wp--preset--spacing--50);
	margin-top: var(--wp--preset--spacing--30);
	border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
}

.shop-category-nav::-webkit-scrollbar {
	display: none;
}

.shop-category-nav__link {
	position: relative;
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: var(--wp--preset--spacing--20) 0;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
	transition: color 150ms ease;
}

.shop-category-nav__link::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: -1px;
	height: 2px;
	background: var(--wp--preset--color--brand-gold-700);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 150ms ease;
}

.shop-category-nav__link:hover,
.shop-category-nav__link:focus-visible {
	color: var(--wp--preset--color--ink);
}

.shop-category-nav__link:hover::after,
.shop-category-nav__link:focus-visible::after {
	transform: scaleX(1);
}

/* Estado ativo via body class nativa do WordPress (tax-product_cat/term-{slug}),
   sem PHP/JS custom. "Todos" fica ativo apenas no Shop puro (post-type-archive-
   product sem tax-product_cat), nunca numa página de categoria. */
body.post-type-archive-product:not(.tax-product_cat) .shop-category-nav__link[href="/shop/"] {
	color: var(--wp--preset--color--ink);
}

body.post-type-archive-product:not(.tax-product_cat) .shop-category-nav__link[href="/shop/"]::after {
	transform: scaleX(1);
}

body.term-telemoveis .shop-category-nav__link[href="/product-category/telemoveis/"],
body.term-iphone .shop-category-nav__link[href="/product-category/iphone/"],
body.term-tablets .shop-category-nav__link[href="/product-category/tablets/"],
body.term-computadores .shop-category-nav__link[href="/product-category/computadores/"],
body.term-smartwatches .shop-category-nav__link[href="/product-category/smartwatches/"],
body.term-audio .shop-category-nav__link[href="/product-category/audio/"],
body.term-tv-e-video .shop-category-nav__link[href="/product-category/tv-e-video/"],
body.term-acessorios .shop-category-nav__link[href="/product-category/acessorios/"],
body.term-gaming .shop-category-nav__link[href="/product-category/gaming/"] {
	color: var(--wp--preset--color--ink);
}

body.term-telemoveis .shop-category-nav__link[href="/product-category/telemoveis/"]::after,
body.term-iphone .shop-category-nav__link[href="/product-category/iphone/"]::after,
body.term-tablets .shop-category-nav__link[href="/product-category/tablets/"]::after,
body.term-computadores .shop-category-nav__link[href="/product-category/computadores/"]::after,
body.term-smartwatches .shop-category-nav__link[href="/product-category/smartwatches/"]::after,
body.term-audio .shop-category-nav__link[href="/product-category/audio/"]::after,
body.term-tv-e-video .shop-category-nav__link[href="/product-category/tv-e-video/"]::after,
body.term-acessorios .shop-category-nav__link[href="/product-category/acessorios/"]::after,
body.term-gaming .shop-category-nav__link[href="/product-category/gaming/"]::after {
	transform: scaleX(1);
}

/* --- Toolbar: contagem + ordenação --- */

.shop-toolbar {
	align-items: center;
	margin-bottom: var(--wp--preset--spacing--30);
	/* .shop-category-nav already draws a border-bottom directly above this
	   row — a second border-top here read as a duplicated separator line. */
	padding-top: var(--wp--preset--spacing--30);
}

.woocommerce-result-count {
	margin: 0;
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
}

.wc-block-catalog-sorting .orderby {
	box-sizing: border-box;
	min-height: 44px;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--sm);
}

.wc-block-catalog-sorting .orderby:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 1px;
	border-color: var(--wp--preset--color--brand-gold-700);
}

/* --- Filtros nativos (categoria/preço/stock) --- */

.shop-filters {
	margin: 0 0 var(--wp--preset--spacing--50);
}

.wc-block-product-filters__open-overlay {
	box-sizing: border-box;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	min-height: 44px;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40);
	background: transparent;
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: var(--wp--custom--radius--md);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	cursor: pointer;
}

.wc-block-product-filters__open-overlay:hover,
.wc-block-product-filters__open-overlay:focus-visible {
	border-color: var(--wp--preset--color--brand-gold-700);
}

.wc-block-product-filters__overlay-dialog {
	background: var(--wp--preset--color--paper);
	border-radius: var(--wp--custom--radius--md);
}

.wc-block-product-filters__close-overlay {
	min-height: 44px;
	min-width: 44px;
	background: transparent;
	border: none;
	color: var(--wp--preset--color--ink);
	cursor: pointer;
}

.shop-filters__group-label {
	margin: 0 0 var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	/* 65% (not the previous 55%) is the minimum ink mix that clears WCAG AA
	   4.5:1 at this font-size/weight — confirmed via axe-core against the
	   rendered sidebar labels. */
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
}

.shop-filters__grid > :first-child .shop-filters__group-label {
	margin-top: 0;
}

.shop-filters__clear {
	margin: 0;
}

/* CP-019: the `core/button` block puts the "btn--text" className on the
   OUTER `.wp-block-button` wrapper div, never on the inner `.wp-block-
   button__link` that actually carries the visible background/text — so
   `.btn--text`'s own rules never reached it, leaving native theme.json
   button defaults (dark bg, 0 padding from the old override below) and
   clipped-looking text. Styled directly here instead: the same quiet
   outlined/neutral treatment as `.btn--secondary`, visually secondary to
   the primary "Adicionar" CTAs in the grid beside it. */
.shop-filters__clear .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40);
	background: transparent;
	border: 1px solid var(--wp--preset--color--ink);
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
	font-weight: 600;
	text-decoration: none;
	transition: background-color 150ms ease, color 150ms ease;
}

.shop-filters__clear .wp-block-button__link:hover {
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--paper);
}

/* Fieldset nativo do WooCommerce sem moldura extra.
   CP-008.2 fix: a classe renderizada é "wp-block-woocommerce-product-filter-checkbox-list"
   (nome padrão do bloco Gutenberg) — o seletor antigo "wc-block-product-filter-checkbox-list"
   nunca correspondia a nenhum elemento real, deixando a borda default do browser para
   <fieldset> (2px groove) visível em Categoria/Disponibilidade, mas não em Preço (que não usa
   fieldset). Isso lia-se como "colisão"/grupos inconsistentes num screenshot real a 1440px. */
.wp-block-woocommerce-product-filter-checkbox-list fieldset {
	margin: 0;
	padding: 0;
	border: none;
	min-inline-size: auto;
}

.wc-block-product-filter-checkbox-list__item {
	margin-bottom: var(--wp--preset--spacing--20);
}

.wc-block-product-filter-checkbox-list__label {
	gap: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm);
}

/* Alvo de toque de 44px nos filtros só é necessário no drawer mobile;
   em desktop os checkboxes ficam mais densos (rato, não toque). */
@media (max-width: 781px) {
	.wc-block-product-filter-checkbox-list__label {
		min-height: 44px;
		align-items: center;
	}
}

.wc-block-product-filter-checkbox-list__count {
	color: color-mix(in srgb, var(--wp--preset--color--ink) 50%, var(--wp--preset--color--paper));
}

.wc-block-product-filter-price-slider__left,
.wc-block-product-filter-price-slider__right {
	box-sizing: border-box;
	max-width: 5.5rem;
	min-height: 36px;
	padding: var(--wp--preset--spacing--20);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--sm);
}

/* The wrapper div above carries the visual box (border/padding/max-width);
   the native <input> inside keeps its own intrinsic width regardless, which
   overflows the wrapper without clipping (divs don't clip children by
   default) — confirmed live in the mobile filter drawer. Force the input to
   fill its already-sized wrapper instead. */
.wc-block-product-filter-price-slider__left input,
.wc-block-product-filter-price-slider__right input {
	width: 100%;
	box-sizing: border-box;
	border: none;
	padding: 0;
}

/* --- Shop filters: vertical grouped list (CP-008.2), sidebar-only (CP-016 correction) ---
   Only from 782px, together with the sidebar layout below — this is the
   "always open" desktop presentation. Below that, filters stay a drawer
   (see the 601–781px block below); there is never a mid-state where the
   full filter panel sits permanently full-width above the grid. */
@media (min-width: 782px) {
	.shop-filters__grid {
		display: flex;
		flex-direction: column;
		gap: var(--wp--preset--spacing--50);
		padding-block: var(--wp--preset--spacing--30);
		border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
		border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
	}

	.shop-filters__grid .shop-filters__group-label {
		margin-top: 0;
	}

	.wp-block-woocommerce-product-filter-price-slider__content {
		max-width: 100%;
	}
}

/* CP-016 correction: WooCommerce's own Product Filters block only keeps its
   mobile drawer/trigger behavior below 601px — from 601px its own CSS
   (`@media (min-width: 601px)`) forces the filter panel permanently inline
   and full-width, which read as "a desktop sidebar's content squeezed into
   a narrow viewport" at 601–781px (real human-reported defect, confirmed
   live: ~800px of filter UI above the first product at 700px). This block
   re-applies Woo's own <601px drawer mechanics (fixed overlay, off-screen
   by default, trigger button, slide-up on .is-overlay-opened — read
   straight from Woo's unscoped base rules) up through 781px, so the drawer
   now covers the same range the sidebar doesn't (see 782px block above). */
@media (min-width: 601px) and (max-width: 781px) {
	.wc-block-product-filters__open-overlay,
	.wc-block-product-filters__overlay-header,
	.wc-block-product-filters__overlay-footer {
		display: flex;
	}

	.wc-block-product-filters__overlay {
		position: fixed;
		inset: var(--top-padding, 0) 0 0 0;
		background-color: transparent;
		pointer-events: none;
		transition: background-color 0.5s;
	}

	.wc-block-product-filters.is-overlay-opened .wc-block-product-filters__overlay {
		background-color: rgba(23, 23, 23, 0.45);
		pointer-events: auto;
		z-index: 9999;
	}

	.wc-block-product-filters__overlay-dialog {
		position: absolute;
		inset: 0;
		max-height: 100%;
		transform: translateY(100vh);
	}

	.wc-block-product-filters.is-overlay-opened .wc-block-product-filters__overlay-dialog {
		transform: translateY(0);
		transition: transform 0.5s;
	}
}

/* Shop desktop layout: sidebar + toolbar + grid. 601–781px keeps filters as
   the drawer above instead: a 260px sidebar there only leaves ~340–460px
   for products, forcing a single artificially wide column (up to ~454px)
   before two 220px+ cards would fit (binary-searched flip: 750–760px).
   782px is this theme's existing tablet breakpoint, comfortably past that
   flip — sidebar only once it actually fits. */
@media (min-width: 782px) {
	.shop-layout {
		display: flex;
		align-items: flex-start;
		gap: var(--wp--preset--spacing--60);
	}

	.shop-layout__sidebar {
		flex: 0 0 260px;
		width: 260px;
		min-width: 0;
	}

	.shop-layout__main {
		flex: 1 1 auto;
		min-width: 0;
	}
}

/* --- Grelha de produtos --- */

.credphone-shop-grid {
	margin-top: var(--wp--preset--spacing--60);
}

/* Isolado a .credphone-shop-grid (CP-007 fix): esta regra aplicava-se antes a QUALQUER
   .wc-block-product-template do site sem scoping, incluindo os Produtos Relacionados da
   página de produto — que usam displayLayout.shrinkColumns:false e por isso ganham a classe
   core "is-flex-container columns-N", cuja regra `.is-flex-container.columns-N>li{width:...}`
   (alta especificidade) colidia com este display:grid, forçando cada card a uma fração de
   coluna já estreita (colapso de texto carácter-a-carácter). A Shop nunca teve este problema
   porque usa shrinkColumns:true, que gera "wc-block-product-template__responsive" em vez de
   "is-flex-container". Scoping evita a colisão sem depender de shrinkColumns em cada uso. */
/* CP-008.2: 170px produzia 6 colunas apertadas a 1440px (largura do conteúdo
   é 1280px mesmo em ecrãs maiores). 220px dá ~4-5 colunas legíveis a 1440,
   reduzindo naturalmente com a sidebar de filtros (auto-fill/minmax, sem
   breakpoints extra a manter) — medido e confirmado via Playwright. */
.credphone-shop-grid .wc-block-product-template {
	display: grid !important;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: var(--wp--preset--spacing--50);
	padding: 0;
	margin: 0;
}

/* --- Home featured-products strip (CP-017) --- */
/* One CSS mechanism handles every product count at every breakpoint — no
   JS decides "grid vs carousel". Cards `flex-grow` to share leftover space
   when few of them fit (looks like a normal filled row, mobile included),
   and `flex-shrink: 0` + `overflow-x: auto` turns the row into a native
   horizontal scroller the moment content actually exceeds the available
   width — the browser's own box model makes that call, not a hardcoded
   breakpoint/count branch. */
.credphone-featured-grid {
	position: relative;
}

/* CP-026: reserve a real control gutter at tablet/desktop widths so the
   arrows frame the rail instead of overlaying the first/last product card.
   Mobile keeps the full-width native strip and hides both arrows in JS. */
@media (min-width: 782px) {
	.credphone-featured-grid {
		box-sizing: border-box;
		padding-inline: 52px;
	}
}

/* CP-029 root cause: `overflow-x: auto` on its own still clips this box's
   content vertically at its own border edges too — the card hover effect
   (translateY(-3px) + a shadow reaching ~18px offset/32px blur below,
   ~4px/10px above) had no room to render there, reading as the shadow
   being "cut" near the top/bottom. Explicitly writing `overflow-y: visible`
   does NOT survive — confirmed live that the browser itself computes it to
   `auto` per spec (pairing one non-visible axis with `visible` on the
   other upgrades the visible one) — so the real fix is vertical `padding`
   on this exact element, which gives the shadow room *inside* the
   scrollable box regardless of which non-visible value `overflow-y` ends
   up as (still doesn't trigger a vertical scrollbar — this element's
   height stays intrinsic/content-driven, so extra padding just makes the
   box taller). The equal-and-opposite vertical `margin` cancels that added
   padding back out for any sibling/ancestor computing this component's
   footprint in normal flow. `margin-top` specifically needed the extra
   `.wc-block-product-template__responsive` class repeated in the selector
   — confirmed live that a WordPress core `.is-layout-flow` rule (same
   0,0,2,0 specificity, later in source order) was winning that one
   property alone, leaving the bottom edge correct but the top edge
   floating 16px lower than intended. Confirmed live afterwards at the
   first, a middle and the last card (an exaggerated-color box-shadow
   swap, temporary/local-only, made the unclipped halo visible on screen).
   Horizontal padding/margin was tried first too but reverted: a matching
   `existing.padding-inline: 52px` on `.credphone-featured-grid` already
   reserves the prev/next arrow gutters, and pulling this track 36px
   outward on each side with a negative margin both pushed the rendered
   cards into those arrow gutters (confirmed live: `featured-carousel-
   cp023b.spec.ts`'s gutter-overlap assertion started failing) and, at
   390/430/768px where there's no equivalent 36px of surrounding gutter to
   absorb it, pulled the whole track past the page's own edge into real
   horizontal overflow (same suite's overflow assertion). The box-shadow
   here has no x-offset at all — only blur — so the existing inter-card
   `gap` already gives every middle card enough side room; only the very
   first/last card's outer edge could theoretically lose a few px of blur,
   accepted as a minor trade-off against reintroducing either regression. */
.credphone-featured-grid .wc-block-product-template.wc-block-product-template__responsive {
	display: flex !important;
	flex-wrap: nowrap;
	overflow-x: auto;
	overflow-y: visible;
	/* CP-018: was `proximity` — didn't guarantee a card-aligned rest
	   position after a drag/arrow/autoplay step (could leave a card half
	   cut off). `mandatory` makes every interaction method (drag, swipe,
	   arrow, autoplay) always settle on a full card, natively — no
	   hand-rolled snap-correction JS needed. */
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
	gap: var(--wp--preset--spacing--30);
	padding-top: 16px;
	padding-bottom: 56px;
	margin-top: -16px;
	margin-bottom: -56px;
}

.credphone-featured-grid .wc-block-product-template::-webkit-scrollbar {
	display: none;
}

/* CP-023B Bloco C3: 220px (was 200px) still comfortably fits 6 cards across
   the 1280px content width at 1440px+ (6 × 220 + 5 × gap ≈ 1210px) without
   compressing the title/price text the old 170px shop-grid value once did
   (see the CP-008.2 comment above `.credphone-shop-grid
   .wc-block-product-template`) — a deliberately composed row, not a
   scroll-truncated one, at the primary desktop width. */
.credphone-featured-grid li.wc-block-product {
	flex: 1 1 220px;
	min-width: 220px;
	max-width: 300px;
	flex-shrink: 0;
	scroll-snap-align: start;
}

.credphone-featured-grid li.credphone-featured-grid__clone {
	pointer-events: none;
	user-select: none;
}

/* Mobile card image swipe (2026-10-14): deliberate resolution of a real
   structural conflict, not an oversight. The featured rail's own
   horizontal touch scroll is 100% native (`overflow-x:auto` +
   `scroll-snap-type:x mandatory` on the track, see CP-023B above) — there
   is no JS to coordinate with, so a `pan-y` image hotspot here would
   fight the rail's own swipe-to-navigate every time a finger starts on a
   product photo (most of the card). Keeping `touch-action: auto` means
   the rail keeps 100% ownership of horizontal touch; `product-card-
   swipe.js` also explicitly refuses to attach inside
   `.credphone-featured-grid` as a second, independent guard. Per-image
   swipe is therefore Shop/Category/Search/Related-only — documented here
   rather than silently decided. */
.credphone-featured-grid .product-card__media {
	touch-action: auto;
}

/* CP-023B Bloco C2: premium merchandising card, strictly scoped to
   `.credphone-featured-grid` (never bare `.credphone-shop-grid`/
   `.product-card__*`, which the Shop archive and PDP related-products
   grid also render through) — the Shop page must render byte-for-byte
   the same as before this task. Larger radius + a resting shadow (not
   only on hover) reads as a distinct, elevated shelf; the image zone's
   background goes to a near-flat neutral (was a faint ink tint) for the
   "extremely clean background" the reference calls for. Real price/
   link/add-to-cart/quantity state and accessibility are all untouched —
   this only restyles surface, radius, shadow, spacing and type scale. */
.credphone-featured-grid li.wc-block-product {
	padding: var(--wp--preset--spacing--40);
	border-color: color-mix(in srgb, var(--wp--preset--color--ink) 6%, transparent);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: 0 1px 3px color-mix(in srgb, var(--wp--preset--color--ink) 6%, transparent);
}

.credphone-featured-grid li.wc-block-product:hover {
	border-color: color-mix(in srgb, var(--wp--preset--color--ink) 6%, transparent);
	box-shadow:
		0 4px 10px color-mix(in srgb, var(--wp--preset--color--ink) 8%, transparent),
		0 18px 32px color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
	transform: translateY(-3px);
}

.credphone-featured-grid .product-card__media {
	margin: calc(var(--wp--preset--spacing--40) * -1) calc(var(--wp--preset--spacing--40) * -1) var(--wp--preset--spacing--30);
	background: color-mix(in srgb, var(--wp--preset--color--ink) 2%, var(--wp--preset--color--paper));
}

/* Sessão de polish visual (2026-09-28): a faixa "Produtos em destaque" da
   Home usa `.credphone-featured-grid`, isolado de `.credphone-shop-grid` por
   desenho (CP-023B acima). O hover de segunda imagem (`.product-card__media-hover`,
   ver `render_block_woocommerce/product-image` no credphone-core.php) já
   cobria o Shop/Category/related-products mas nunca foi replicado aqui —
   mesmo gate `hover: hover` + `pointer: fine` para nunca "colar" no touch. */
/* Mesmo fix de root cause do bloco .credphone-shop-grid acima (2026-10-13):
   ancorado em .product-card__media, não no cartão inteiro. */
@media (hover: hover) and (pointer: fine) {
	.credphone-featured-grid .product-card__media:hover .product-card__media-hover,
	.credphone-featured-grid .product-card__media:focus-within .product-card__media-hover {
		opacity: 1;
	}

	/* Same ghosting fix as .credphone-shop-grid above (2026-09-30) — the
	   primary image must crossfade OUT as the overlay fades in, not stay
	   at full opacity underneath a transparent-background PNG. */
	.credphone-featured-grid .product-card__media:hover img[data-testid="product-image"]:has(+ .product-card__media-hover),
	.credphone-featured-grid .product-card__media:focus-within img[data-testid="product-image"]:has(+ .product-card__media-hover) {
		opacity: 0;
	}
}

.credphone-featured-grid li.wc-block-product[data-credphone-color-image-selected="true"] .product-card__media:hover img[data-testid="product-image"],
.credphone-featured-grid li.wc-block-product[data-credphone-color-image-selected="true"] .product-card__media:focus-within img[data-testid="product-image"] {
	opacity: 1;
}

.credphone-featured-grid .product-card__name {
	font-weight: 700;
}

.credphone-featured-grid .price {
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 700;
}

/* CP-023B Bloco C1: quiet, precise rail controls — a real chevron (already
   in the markup), a plain circle with a hairline border instead of the old
   heavy `--elevation--raised` shadow, sized to the image zone's vertical
   center (`top: 38%` — NOT the card's full height, which would land the
   arrow over the title/price/CTA text; "never over critical content" per
   the Product Owner) so it reads as framing the product shelf, not
   sitting on top of it. */
.credphone-featured-grid__arrow {
	position: absolute;
	top: 38%;
	transform: translateY(-50%);
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	padding: 0;
	background: var(--wp--preset--color--paper);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 14%, transparent);
	border-radius: 50%;
	box-shadow: 0 2px 8px color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
	color: var(--wp--preset--color--ink);
	cursor: pointer;
	transition: background-color 150ms ease, border-color 150ms ease, box-shadow 150ms ease, transform 150ms ease;
}

/* [hidden] vs an authored `display` value is a recurring bug in this
   codebase (same fix already applied to the mini-cart image, financing-hub
   controls, etc.) — an attribute selector and a class selector tie on
   specificity, so without this override (placed AFTER the conflicting
   rule — equal-specificity ties are broken by source order) the
   JS-toggled `hidden` attribute would lose to `display: flex` above. */
.credphone-featured-grid__arrow[hidden] {
	display: none;
}

.credphone-featured-grid__arrow:hover,
.credphone-featured-grid__arrow:focus-visible {
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 12%, var(--wp--preset--color--paper));
	border-color: color-mix(in srgb, var(--wp--preset--color--brand-gold) 40%, transparent);
	box-shadow: 0 4px 14px color-mix(in srgb, var(--wp--preset--color--ink) 16%, transparent);
}

@media (hover: hover) and (pointer: fine) {
	.credphone-featured-grid__arrow:hover {
		transform: translateY(-50%) scale(1.06);
	}
}

.credphone-featured-grid__arrow:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.credphone-featured-grid__arrow:hover {
		transform: translateY(-50%);
	}
}

/* Inset a small amount from the rail's own edge (not offset past it) —
   this section has zero side gutter below 1280px (verified against the
   rest of the homepage), so a negative offset here would push the arrow
   past the viewport edge and cause real horizontal page overflow. A
   shallow inset at the outer edge (was 20px, now 10px — closer to the
   rail's true edge, per the Product Owner's "outer edge" direction) stays
   overflow-safe while reading as bracketing the row rather than sitting
   deep inside a card's image. */
.credphone-featured-grid__arrow--prev {
	left: 6px;
}

.credphone-featured-grid__arrow--next {
	right: 6px;
}

.credphone-shop-grid li.wc-block-product {
	min-width: 0;
	/* Contorno mais discreto do que o preto pleno herdado de .product-card. */
	border-color: color-mix(in srgb, var(--wp--preset--color--ink) 14%, transparent);
	transition: border-color 150ms ease;
}

.credphone-shop-grid li.wc-block-product:hover {
	border-color: color-mix(in srgb, var(--wp--preset--color--ink) 30%, transparent);
}

/* Same edge-to-edge image treatment as .product-card__media (§9/§12): the
   image bleeds to the card's own edges instead of sitting inside its
   padding, for a stronger, more product-forward shelf presence. */
.credphone-shop-grid .wc-block-components-product-image {
	position: relative;
	aspect-ratio: 1 / 1;
	margin: calc(var(--wp--preset--spacing--30) * -1) calc(var(--wp--preset--spacing--30) * -1) var(--wp--preset--spacing--30);
	background: color-mix(in srgb, var(--wp--preset--color--ink) 3%, var(--wp--preset--color--paper));
	border-radius: var(--wp--custom--radius--md) var(--wp--custom--radius--md) 0 0;
	overflow: hidden;
}

/* WooCommerce's product-image block ("imageSizing":"thumbnail") prints
   `style="object-fit:cover;aspect-ratio:1/1;"` as an inline attribute on
   the <img> itself (confirmed live) — crops any non-square product photo
   and would clip a real packshot's edges. Only an `!important` external
   rule can beat an inline style, same pattern already used for the mini-
   cart badge above. Contain + internal padding shows the whole product
   instead, matching the PDP gallery treatment and the category cards'
   media zones — one consistent "whole product, never cropped" rule
   across the site. The container keeps its own edge-to-edge box (comment
   above); the padding lives on the image itself so the photo still gets
   breathing room without losing that edge-to-edge shelf feel. */
.credphone-shop-grid .wc-block-components-product-image img {
	width: 100%;
	height: 100%;
	object-fit: contain !important;
	object-position: center;
	padding: var(--wp--preset--spacing--30);
	box-sizing: border-box;
	border-radius: inherit;
}

/* Bug real reportado pelo PO (2026-10-14): no slider "Produtos em destaque"
   mobile, a mesma imagem renderizava ora a ~275px ora a ~241px — nunca
   proporcional à viewport, inconsistente entre cartões com o MESMO HTML
   (confirmado byte-a-byte via Playwright). Causa raiz: o `<img>` do Woo
   vive dentro de um `<a>` que é irmão de flex de uma
   `.wc-block-components-product-image__inner-container` sempre vazia —
   nenhum dos dois tinha largura explícita. Sem isso, o `<a>` (um item de
   flex com `width:auto`) é dimensionado pelo algoritmo "shrink-to-fit" do
   motor a partir do tamanho intrínseco da PRÓPRIA imagem, e só depois é que
   a regra `width:100%` acima resolve a percentagem contra esse resultado —
   em vez de resolver contra a caixa 1:1 que este `.product-card__media`
   já reserva. Resultado observado ao vivo: o mesmíssimo produto, com HTML
   idêntico, aterra em larguras diferentes consoante o motor já tinha ou
   não resolvido o tamanho natural da imagem nesse load específico. Dar ao
   `<a>` uma caixa 100% explícita remove a ambiguidade na raiz. */
.credphone-shop-grid .wc-block-components-product-image a {
	display: block;
	width: 100%;
	height: 100%;
}

/* Evita colidir com o placeholder de wishlist (canto superior direito). */
.credphone-shop-grid .wc-block-components-product-sale-badge {
	inset-inline-end: auto;
	inset-inline-start: var(--wp--preset--spacing--20);
}

/* Woo's own default wrapper draws a grey box/border around the badge
   (human-reported: "looks rough, arbitrary black outline") — the gold pill
   below is the only visible badge; the wrapper is neutralised to a plain
   positioning box. */
.credphone-shop-grid .wc-block-components-product-sale-badge {
	background: none;
	border: none;
	padding: 0;
}

.credphone-shop-grid .wc-block-components-product-sale-badge__text {
	display: inline-flex;
	padding: 0.2rem var(--wp--preset--spacing--30);
	background: var(--wp--preset--color--brand-gold);
	color: var(--wp--preset--color--ink);
	border-radius: var(--wp--custom--radius--sm);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
}

/* Generalizado de .credphone-shop-grid para .price (CP-007): o desconto
   risco/preço-atual não é específico da Shop — o mesmo .price aparece agora
   também no painel de compra da página de produto. Reaproveitado em vez de
   duplicado. */
.price .woocommerce-Price-amount {
	font-size: inherit;
	font-weight: inherit;
}

.price del .woocommerce-Price-amount {
	font-weight: 400;
	opacity: 0.6;
}

.price del {
	margin-right: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm);
}

/* Badge de financiamento mais discreto na Shop, para não competir com o preço. */
.credphone-shop-grid .product-card__financing {
	padding: 0.2rem var(--wp--preset--spacing--20);
	font-size: 0.7rem;
	background: transparent;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 60%, var(--wp--preset--color--paper));
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 25%, transparent);
}

/* Nome do produto com altura reservada para 2 linhas, para alinhar os cards
   mesmo com nomes longos vindos do catálogo real. */
.credphone-shop-grid .product-card__name {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	min-height: calc(2 * var(--wp--preset--font-size--base) * 1.35);
	font-size: var(--wp--preset--font-size--base);
	line-height: 1.35;
}

.credphone-shop-grid .product-card__name a {
	text-decoration: none;
	color: inherit;
}

.credphone-shop-grid .product-card__name a:hover {
	color: var(--wp--preset--color--brand-gold-700);
}

.product-card__stock {
	margin-bottom: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	color: var(--wp--preset--color--success);
}

/* Tinted status chips (CP-016 human correction: "must not look like raw red
   plugin text") instead of bare colored text — restrained, but each state
   reads as intentional and distinct from price/badges. No delivery date or
   other unverified claim added. */
.wc-block-components-product-stock-indicator--out-of-stock,
.wc-block-components-product-stock-indicator--available-on-backorder {
	display: inline-flex;
	padding: 0.15rem var(--wp--preset--spacing--20);
	border-radius: var(--wp--custom--radius--sm);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
}

.wc-block-components-product-stock-indicator--out-of-stock {
	background: color-mix(in srgb, var(--wp--preset--color--error) 12%, var(--wp--preset--color--paper));
	color: var(--wp--preset--color--error);
}

.wc-block-components-product-stock-indicator--available-on-backorder {
	background: color-mix(in srgb, var(--wp--preset--color--warning) 12%, var(--wp--preset--color--paper));
	color: var(--wp--preset--color--warning);
}

/* --- Paginação --- */

.shop-pagination.wp-block-query-pagination {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 2px;
	width: fit-content;
	max-width: 100%;
	margin: var(--wp--preset--spacing--60) auto 0;
	padding: 4px;
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 14%, transparent);
	border-radius: var(--wp--custom--radius--lg);
	background: var(--wp--preset--color--paper);
	box-shadow: var(--wp--custom--elevation--raised);
}

.shop-pagination .wp-block-query-pagination-numbers {
	display: flex;
	align-items: center;
	gap: 2px;
	margin: 0;
}

.shop-pagination .wp-block-query-pagination-previous,
.shop-pagination .wp-block-query-pagination-next,
.shop-pagination__first,
.shop-pagination__last,
.shop-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	height: 44px;
	margin: 0;
	padding: 0 0.65rem;
	border: 1px solid transparent;
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 650;
	line-height: 1;
	text-decoration: none;
	transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease;
}

.shop-pagination .page-numbers.dots {
	min-width: 20px;
	padding: 0;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 55%, transparent);
	user-select: none;
}

/* Active page uses a perfect circle, not the shared rounded-rect of the
   other controls — width pinned equal to height (not just min-width) so
   `border-radius: 50%` renders a true circle instead of a rounded pill;
   3-class specificity already beats the 2-class shared rule and the
   `padding-inline` override in the <=480px block below, so no !important
   needed. */
.shop-pagination .page-numbers.current {
	width: 44px;
	height: 44px;
	padding: 0;
	border-radius: 50%;
	border-color: var(--wp--preset--color--brand-gold);
	background: var(--wp--preset--color--brand-gold);
	color: var(--wp--preset--color--ink);
	font-weight: 750;
}

.shop-pagination a:hover {
	border-color: color-mix(in srgb, var(--wp--preset--color--brand-gold-700) 24%, transparent);
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 12%, var(--wp--preset--color--paper));
	color: var(--wp--preset--color--brand-gold-700);
}

.shop-pagination a:focus-visible {
	position: relative;
	z-index: 1;
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 2px;
}

.shop-pagination .wp-block-query-pagination-previous-arrow,
.shop-pagination .wp-block-query-pagination-next-arrow,
.shop-pagination__first span,
.shop-pagination__last span {
	margin: 0;
	font-size: 1.15rem;
	line-height: 1;
}

.shop-pagination__context {
	display: none;
}

@media (prefers-reduced-motion: reduce) {
	.shop-pagination a {
		transition: none;
	}
}

@media (max-width: 480px) {
	.shop-pagination.wp-block-query-pagination {
		flex-wrap: wrap;
		width: 100%;
		padding: 6px 4px;
	}

	.shop-pagination__context {
		display: block;
		order: -1;
		flex: 0 0 100%;
		padding: 0.15rem 0.5rem 0.35rem;
		color: color-mix(in srgb, var(--wp--preset--color--ink) 72%, transparent);
		font-size: var(--wp--preset--font-size--sm);
		font-weight: 600;
		line-height: 1.3;
		text-align: center;
	}

	.shop-pagination .wp-block-query-pagination-previous,
	.shop-pagination .wp-block-query-pagination-next,
	.shop-pagination__first,
	.shop-pagination__last,
	.shop-pagination .page-numbers {
		padding-inline: 0.45rem;
	}

	.shop-pagination .page-numbers:not(.current) {
		display: none;
	}
}

/* --- Estado vazio --- */

.shop-empty-state {
	margin-top: var(--wp--preset--spacing--50);
	text-align: center;
}

@media (max-width: 480px) {
	.shop-toolbar {
		align-items: flex-start;
		flex-direction: column;
		gap: var(--wp--preset--spacing--20);
	}
}

/* =========================================================
   Página de produto (CP-007)
   Reutiliza componentes/tokens existentes (.badge, .btn,
   .icon-btn, .price, .trust-inline, .credphone-shop-grid,
   .product-card*, regra de estado [disabled] global) sempre
   que possível. Seletores contra classes do WooCommerce
   confirmados no HTML real renderizado pelo wp-env
   (WooCommerce 11.0.1) para os 5 fixtures de QA
   (simples/variável/promoção/esgotado/backorder), não
   adivinhados.
   ========================================================= */

.site-main--product {
	padding-top: var(--wp--preset--spacing--50);
}

/* --- Galeria + painel de compra --- */

.product-hero {
	gap: var(--wp--preset--spacing--70) !important;
	margin-bottom: var(--wp--preset--spacing--70);
}

.product-hero__gallery {
	min-width: 0;
}

/* CP-021: was `height:auto` on the placeholder image only — real product
   photos (`.woocommerce-product-gallery__image`, no `--placeholder`
   modifier) had no rule at all, so they'd render at whatever aspect ratio
   the source file happened to have: cropped-looking on a wide photo,
   comically tall on a portrait one, and a transparent-background packshot
   would visually "disappear" into the page's white background. Same fixed
   1:1 stage + `object-fit: contain` + tinted background the Shop grid
   cards already use, so PDP and Shop read as one consistent system. */
.woocommerce-product-gallery__wrapper,
.woocommerce-product-gallery__image--placeholder,
.woocommerce-product-gallery__image {
	border-radius: var(--wp--custom--radius--md);
	overflow: hidden;
	background: color-mix(in srgb, var(--wp--preset--color--ink) 3%, var(--wp--preset--color--paper));
}

.woocommerce-product-gallery__image--placeholder img,
.woocommerce-product-gallery__image img {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: contain;
	padding: var(--wp--preset--spacing--40);
	box-sizing: border-box;
}

/* O badge nativo .onsale da galeria clássica vem como círculo decorativo
   posicionado parcialmente fora da caixa (left:-16px) — confirmado no HTML
   real (fixture em promoção), fica cortado visualmente. Reestilizado como
   pill consistente com o badge de promoção já usado nos cards da Shop. */
/* !important necessário: o WooCommerce imprime
   ".woocommerce .wp-block-woocommerce-product-image-gallery span.onsale"
   (especificidade 0,3,1) inline no <head>, mais específico do que qualquer
   seletor plausível daqui sem repetir a mesma cadeia de classes. */
.product-hero__gallery .onsale {
	position: absolute !important;
	top: var(--wp--preset--spacing--30) !important;
	left: var(--wp--preset--spacing--30) !important;
	right: auto !important;
	min-width: 0 !important;
	min-height: 0 !important;
	margin: 0 !important;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30) !important;
	border-radius: var(--wp--custom--radius--pill) !important;
	background: var(--wp--preset--color--brand-gold) !important;
	color: var(--wp--preset--color--ink) !important;
	font-size: var(--wp--preset--font-size--sm) !important;
	font-weight: 600 !important;
	line-height: 1 !important;
	text-align: center !important;
}

.product-hero__summary {
	position: relative;
	min-width: 0;
}

/* --- Wishlist placeholder (mesmo padrão aria-disabled do header/CP-006) --- */

.product-summary__wishlist {
	position: absolute;
	top: 0;
	right: 0;
}

.product-summary__title {
	margin: 0 var(--wp--preset--spacing--70) var(--wp--preset--spacing--30) 0;
}

.product-summary__rating:not(:empty) {
	margin-bottom: var(--wp--preset--spacing--30);
}

.product-summary__price {
	margin-bottom: var(--wp--preset--spacing--30);
}

/* --- Formulário nativo de compra (simples e variável, WooCommerce trata tudo) --- */

/* CP-029: was `spacing--30` (~11px) — read as cramped against "Pagamento
   em prestações" right below (brief §21: "spacing suficiente... não
   deixar o bloco parecer amontoado"). The row-gap *inside* the form
   (quantity/add-to-cart row -> Buy Now row) stays the smaller, deliberate
   `spacing--30` — only the gap *after* the whole purchase block grows. */
.product-summary__form {
	margin-bottom: var(--wp--preset--spacing--60);
}

/* Positioning/UX pass — PDP purchase actions: quantity + "Adicionar ao
   carrinho" (a full textual secondary button — the PDP has real room for
   it, unlike the compact icon-only control on Shop/Category cards) share
   one row; "Comprar agora" spans a full-width row below, genuinely
   dominant. Root cause of the original defect (quantity + two
   `single_add_to_cart_button`s, each independently `display: inline-flex`,
   direct children of the real `<form class="cart">` WooCommerce renders,
   with no shared row container of their own) was plain inline wrapping —
   three inline-level boxes flowing and breaking like words once their
   combined width ran out, exactly why "Adicionar" fell onto its own line
   unpredictably instead of at a controlled breakpoint. A real 2-row grid
   fixes this at every width — no separate mobile-only variant needed.
   `.variations_button` (`.woocommerce-variation-add-to-cart`) is the
   equivalent grid container WooCommerce Blocks uses for a VARIABLE
   product instead of `form.cart` directly — confirmed live: for a
   variable product, `form.cart`'s own direct children are `.variations`
   (the attribute table), a screen-reader-only alert, and
   `.single_variation_wrap`, which itself contains `.variations_button`
   wrapping the real quantity/button trio once a variation resolves.
   WooCommerce Blocks already pairs the two contexts throughout its own
   stylesheet (`.variations_button, form.cart { … }`) — every rule below
   does the same so both product types share one implementation. */
.product-summary__form form.cart,
.product-summary__form .variations_button {
	display: grid;
	grid-template-columns: auto 1fr;
	grid-auto-flow: row;
	align-items: stretch;
	column-gap: var(--wp--preset--spacing--20);
	row-gap: var(--wp--preset--spacing--30);
}

/* WooCommerce core's legacy float-layout clearfix (`.woocommerce div.product
   form.cart::before, ::after { content: " "; display: table }`,
   specificity 0,0,3,3) is dead weight once this form is a grid container
   (grids establish their own formatting context — nothing here floats) but
   very much alive as far as the grid itself is concerned: a real grid item
   with `grid-column: 1 / -1` (from the same WooCommerce Blocks stylesheet),
   auto-placed ahead of our three real children in tree order. Confirmed
   live: with the clearfix pseudo-elements still generating content, the
   icon and "Comprar agora" buttons rendered stretched to a ~568px-tall
   phantom row and visually overlapping — `content: none` here (0,0,4,3,
   beating the clearfix rule) removes them from generating any box at all,
   which is exactly what removing dead clearfix should do anyway. */
.product-summary__form.wc-block-add-to-cart-form.wp-block-woocommerce-add-to-cart-form form.cart::before,
.product-summary__form.wc-block-add-to-cart-form.wp-block-woocommerce-add-to-cart-form form.cart::after {
	content: none;
}

/* CP-029: an explicit, equal `height` on both row-1 controls (not just
   `min-height` + the grid's own `align-items: stretch`) — the quantity
   selector and "Adicionar ao carrinho" build up their box height from
   different internal content (a bordered flex row of 42px sub-controls
   vs. this theme's own button padding), so relying on stretch to make two
   differently-computed intrinsic heights *end up* equal left a visible
   few-pixel mismatch confirmed live. A shared value on both removes the
   ambiguity outright regardless of either one's internal content. */
.product-summary__form .wc-block-components-quantity-selector {
	grid-column: 1;
	grid-row: 1;
	height: 52px;
	margin-bottom: 0;
}

/* WooCommerce Blocks already turns this exact form into its own native
   CSS Grid (`.wp-block-woocommerce-add-to-cart-form form.cart { display:
   grid; grid-template-columns: min-content auto auto }`, confirmed live —
   this theme's own `.product-summary__form form.cart` rule above already
   wins the *template* by source order at equal 0,0,2,0 specificity) and,
   critically, places every `.single_add_to_cart_button` — both of ours —
   into the identical `grid-column: 2 / 3` via its own more specific
   `.wp-block-woocommerce-add-to-cart-form form.cart > .single_add_to_cart_
   button` rule (0,0,2,0, beating a plain one-class override). Repeating
   that exact selector chain plus our own classes (0,0,3,0) is what
   actually separates "Adicionar ao carrinho" (row 1, column 2) from
   "Comprar agora" (row 2, spanning both columns) instead of both stacking
   into the same cell — confirmed live via the browser's own matched-rules
   list, not guessed. */
.wp-block-woocommerce-add-to-cart-form form.cart > .single_add_to_cart_button.product-summary__add-secondary,
.wp-block-woocommerce-add-to-cart-form .variations_button > .single_add_to_cart_button.product-summary__add-secondary {
	grid-column: 2;
	grid-row: 1;
	/* WooCommerce Blocks' own stylesheet sets `justify-self: start` on this
	   same selector (its 3-column `auto auto auto` template didn't need the
	   button to fill its track) — confirmed live via getComputedStyle. Since
	   our `1fr` second column exists specifically so this button's right
	   edge reaches the row's true right edge (matching "Comprar agora" below,
	   per the brief), the button must fill that track rather than sit at its
	   own content width inside it. */
	justify-self: stretch;
}

.wp-block-woocommerce-add-to-cart-form form.cart > .single_add_to_cart_button.product-summary__buy-now,
.wp-block-woocommerce-add-to-cart-form .variations_button > .single_add_to_cart_button.product-summary__buy-now {
	grid-column: 1 / -1;
	grid-row: 2;
	width: 100%;
}

/* A mensagem de stock já vem duplicada pelo woocommerce/product-stock-indicator
   dedicado (abaixo), com classes semânticas e posição consistente com os cards
   da Shop — evita mostrar o mesmo texto duas vezes no painel. */
.product-summary__form .stock {
	display: none;
}

.product-summary__form .variations {
	width: 100%;
	max-width: 420px;
	margin-bottom: var(--wp--preset--spacing--40);
	border-collapse: collapse;
}

.product-summary__form .variations td,
.product-summary__form .variations th {
	position: relative;
	padding: 0 0 var(--wp--preset--spacing--30);
	text-align: left;
	/* CP-021 Round 4 Gate 4: "top" left the "Armazenamento" label sitting
	   noticeably higher than its own <select> (the label's line-box is
	   shorter than the select's rendered height, so top-alignment reads
	   as uneven) — confirmed live. "middle" is the correct vertical-align
	   for a real <table> cell layout (this is WooCommerce core's own
	   variation-form markup, a genuine <table>, not a flex/grid — see
	   border-collapse above), and reads as properly paired now. */
	vertical-align: middle;
}

.product-summary__form .variations label {
	font-weight: 600;
	font-size: var(--wp--preset--font-size--sm);
}

/* appearance:none + a CSS-drawn chevron replace the OS-default arrow this
   already-styled select still had (DESIGN.md: "a control that still looks
   like an unstyled plugin surface is unfinished") — box styling unchanged. */
.product-summary__form select {
	box-sizing: border-box;
	width: 100%;
	max-width: 320px;
	min-height: 44px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--70) var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
	appearance: none;
	cursor: pointer;
}

.product-summary__form .variations td.value::after {
	content: "";
	position: absolute;
	top: 22px;
	right: var(--wp--preset--spacing--40);
	width: 8px;
	height: 8px;
	border-right: 2px solid var(--wp--preset--color--ink);
	border-bottom: 2px solid var(--wp--preset--color--ink);
	transform: translateY(-70%) rotate(45deg);
	pointer-events: none;
}

.product-summary__form select:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 1px;
	border-color: var(--wp--preset--color--brand-gold-700);
}

.product-summary__form .reset_variations {
	margin-left: var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
}

/* --- PDP colour swatches (progressive enhancement, pdp-color-swatches.js) ---
   The class below is added by JS only, at runtime — with JS disabled this
   selector never matches and the native <select> stays exactly as
   WooCommerce renders it (the ".product-summary__form select" rule above).
   `position: absolute` + a 1px box (not `display: none`) keeps the element
   a real, valid form control WooCommerce's own scripts can still read/set;
   the script itself also sets tabIndex=-1 and aria-hidden so it is neither
   a keyboard stop nor announced twice next to the swatch group replacing
   it visually. */
.product-summary__form select.is-credphone-enhanced {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
}

.product-summary__form .variations td.value:has(select.is-credphone-enhanced)::after {
	content: none;
}

.pdp-color-swatches {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	margin-bottom: var(--wp--preset--spacing--20);
}

.pdp-color-swatch {
	box-sizing: border-box;
	display: inline-grid;
	place-items: center;
	width: 38px;
	height: 38px;
	padding: 0;
	background: transparent;
	border: 1px solid transparent;
	border-radius: 50%;
	cursor: pointer;
	transition: transform 150ms ease, border-color 150ms ease, box-shadow 150ms ease;
}

.pdp-color-swatch > span {
	display: block;
	width: 30px;
	height: 30px;
	background: var(--credphone-swatch-color, color-mix(in srgb, var(--wp--preset--color--ink) 10%, var(--wp--preset--color--paper)));
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 30%, transparent);
	border-radius: 50%;
	box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--wp--preset--color--paper) 55%, transparent);
}

.pdp-color-swatch[data-credphone-swatch-pattern="camo"] > span {
	background: repeating-linear-gradient(
		135deg,
		#5b5a45 0 6px,
		#43492f 6px 12px,
		#2c2e22 12px 17px,
		#6b6a52 17px 23px
	);
}

@media (hover: hover) and (pointer: fine) {
	.pdp-color-swatch:not(:disabled):hover {
		transform: scale(1.08);
	}
}

.pdp-color-swatch.is-selected {
	border-color: var(--wp--preset--color--ink);
	box-shadow: 0 0 0 2px var(--wp--preset--color--paper), 0 0 0 3.5px color-mix(in srgb, var(--wp--preset--color--ink) 65%, transparent);
}

.pdp-color-swatch:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 3px;
}

.pdp-color-swatch:disabled {
	cursor: not-allowed;
	opacity: 0.35;
}

.pdp-color-swatch:disabled > span {
	background-image: linear-gradient(
		to top right,
		transparent calc(50% - 1px),
		color-mix(in srgb, var(--wp--preset--color--ink) 55%, transparent) calc(50% - 1px) calc(50% + 1px),
		transparent calc(50% + 1px)
	);
}

.pdp-color-swatches__current {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 75%, var(--wp--preset--color--paper));
}

.pdp-color-swatches__current strong {
	color: var(--wp--preset--color--ink);
	font-weight: 700;
}

/* Same 781px breakpoint the rest of this theme's responsive rules use —
   larger touch target on mobile/touch, per the approved PDP spec. */
@media (max-width: 781px) {
	.pdp-color-swatch {
		width: 44px;
		height: 44px;
	}

	.pdp-color-swatch > span {
		width: 36px;
		height: 36px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.pdp-color-swatch:hover {
		transform: none;
	}
}

/* CP-021 Round 4 Gate 4: the PDP's own quantity stepper is taller than
   the cart's (stretched to match the Add to Cart button here) — a later,
   cart-focused `.wc-block-components-quantity-selector__button` rule
   elsewhere in this file (unscoped, same specificity, wins by source
   order) never centers a button's own glyph vertically, only barely
   noticeable in the cart's shorter 46px box but clearly off-center here
   (confirmed live: "−"/"1"/"+" all sat near the top with empty space
   below). Scoped to this form only — the cart's own appearance is left
   exactly as it already was. */
.product-summary__form .wc-block-components-quantity-selector__button {
	display: flex;
	align-items: center;
	justify-content: center;
}

/* Pre-client polish: the "1" sat visibly higher than the −/+ glyphs. Root
   cause is WooCommerce Blocks' own inline critical CSS for the stepper add-
   to-cart variant — `div.wc-block-add-to-cart-form.wc-block-add-to-cart-
   form--stepper .wc-block-components-quantity-selector input[type="number"]
   .input-text.qty.text { padding: 0.9rem 0 }` plus a second inline rule
   forcing `box-sizing: content-box` on the same input — together inflating
   its real height to ~71px against the buttons' 44px, so "centering" the
   glyph inside that oversized, content-box-padded box left it near the top.
   Both are auto-generated per block instance (not a stylesheet we can just
   load after), at a specificity the previous `padding-block:0` override
   (two classes) never actually beat — confirmed live via the browser's own
   matched-rules list, not guessed. This selector repeats the exact class/
   attribute set WooCommerce prints plus `.product-summary__form`, so it
   wins on specificity alone, no !important. */
div.wc-block-add-to-cart-form.wc-block-add-to-cart-form--stepper.product-summary__form .wc-block-components-quantity-selector input[type="number"].input-text.qty.text {
	box-sizing: border-box;
	padding: 0;
	line-height: normal;
}


.wc-block-components-quantity-selector {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	margin-bottom: var(--wp--preset--spacing--30);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	overflow: hidden;
}

.wc-block-components-quantity-selector__input {
	box-sizing: border-box;
	width: 3.5rem;
	min-height: 42px;
	border: none;
	text-align: center;
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
	background: transparent;
}

.wc-block-components-quantity-selector__button {
	min-width: 44px;
	min-height: 42px;
	border: none;
	background: color-mix(in srgb, var(--wp--preset--color--ink) 4%, var(--wp--preset--color--paper));
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--lg);
	cursor: pointer;
}

.wc-block-components-quantity-selector__button:hover {
	background: color-mix(in srgb, var(--wp--preset--color--ink) 10%, var(--wp--preset--color--paper));
}

.single_add_to_cart_button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	margin-left: var(--wp--preset--spacing--30);
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--60);
	background: var(--wp--preset--color--brand-gold);
	border: 1px solid var(--wp--preset--color--brand-gold);
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
	font-weight: 600;
	cursor: pointer;
	transition: filter 150ms ease;
}

.single_add_to_cart_button:hover {
	filter: brightness(0.93);
}

.single_add_to_cart_button:active {
	filter: brightness(0.87);
}

/* --- Positioning/UX pass: "Comprar agora" (primary, inherits the gold
   .single_add_to_cart_button look above) sits first; the native "Adicionar"
   becomes the visibly secondary action next to it — commerce hierarchy
   brief: purchase must outrank every other PDP control, prestações/WhatsApp
   included. --- */

/* CP-029: "Comprar agora" reads as the dominant action partly through a
   subtly taller box than the row above it (brief §20 — "upper controls:
   ~50-52px, Buy Now: ~56px", a deliberately small difference, not a size
   jump). `margin-inline` on this exact grid item — not the grid's own gap
   or the row above's own width — is what keeps its left/right edges
   flush with the combined span of quantity + "Adicionar ao carrinho"
   below it (`grid-column: 1 / -1` already guarantees that on its own;
   this only resets the unrelated horizontal margin the shared
   `.single_add_to_cart_button` base rule puts on every button of this
   class for the Shop-card and other non-grid contexts it's also used
   in). */
.product-summary__buy-now {
	height: 56px;
	margin-left: 0;
}

.product-summary__buy-now + .product-summary__add-secondary {
	margin-left: var(--wp--preset--spacing--20);
}

.product-summary__add-secondary {
	height: 52px;
	background: var(--wp--preset--color--paper);
	border-color: color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	color: var(--wp--preset--color--ink);
	/* Visual micro-polish: the base .single_add_to_cart_button horizontal
	   padding (36px a side) left "Adicionar ao carrinho" ~6px short of
	   fitting on one line at 390px width — confirmed live. Same fix as the
	   card's "Comprar agora" padding reduction; comfortably still exceeds a
	   real touch target. */
	padding-inline: 16px;
}

.product-summary__add-secondary:hover {
	background: color-mix(in srgb, var(--wp--preset--color--ink) 4%, var(--wp--preset--color--paper));
	filter: none;
}

/* Before a valid variation is chosen, WooCommerce marks this same button
   `.disabled` and renders it at 50% opacity via its own
   `woocommerce-blocktheme.css` (`.woocommerce button.button.disabled`,
   3 classes — needs matching/higher specificity here to win, not load
   order) — the button stays a real, focusable/clickable control (no
   `disabled` attribute, no `pointer-events:none`), so its dimmed gold-on-ink
   blends toward the white page background to ~2.5:1, failing WCAG AA. Solid
   ink/paper neutrals at full opacity read just as clearly as "not ready yet"
   without losing contrast — same tokens used for dividers/quiet surfaces
   elsewhere in this file. */
.woocommerce button.single_add_to_cart_button.disabled {
	opacity: 1;
	background: color-mix(in srgb, var(--wp--preset--color--ink) 8%, var(--wp--preset--color--paper));
	border-color: color-mix(in srgb, var(--wp--preset--color--ink) 20%, transparent);
	color: var(--wp--preset--color--ink);
}

.woocommerce button.single_add_to_cart_button.disabled:hover,
.woocommerce button.single_add_to_cart_button.disabled:active {
	filter: none;
}

/* --- Indicador de stock dedicado (esconde-se nativamente quando em stock;
   cores --out-of-stock/--available-on-backorder já definidas mais acima) --- */

.product-summary__stock {
	display: block;
	margin-bottom: var(--wp--preset--spacing--40);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
}

/* --- CTA secundário WhatsApp (CP-010): o shortcode [credphone_whatsapp_cta]
   renderiza a própria âncora sem wrapper — quando credphone_whatsapp_number
   não está configurado, o shortcode devolve string vazia e esta classe não
   existe em lado nenhum do DOM, logo zero espaçamento residual. --- */

/* Positioning/UX pass: on the PDP, WhatsApp is support/fallback contact —
   it must not carry the same visual weight as the purchase CTA above it
   (brief §9: "não deve ter peso visual igual/superior ao CTA principal").
   Markup now carries `.btn--text` instead of `.btn--secondary` (see
   credphone-core.php), which already gives it the quiet-link treatment
   (no fill/border, no hover halo) — only the icon needs resizing down to
   match that smaller footprint. The Home "support" context keeps the full
   `.btn--secondary` button; it has no purchase CTA to compete with. */
.whatsapp-cta--product {
	margin-bottom: var(--wp--preset--spacing--40);
}

.whatsapp-cta--product .whatsapp-cta__icon {
	width: 18px;
	height: 18px;
}

.whatsapp-cta__icon {
	width: 20px;
	height: 20px;
	flex-shrink: 0;
}

/* --- CP-009B.1: CTA "Simular financiamento" na PDP (link real para
   /pagamento-em-prestacoes/, não um dialog). CP-009A's original <dialog>-based CTA
   and its dedicated CSS were removed in the CP-009B.1 correctness pass —
   genuinely dead once nothing rendered the dialog anymore (git history has
   the previous rules). The intl-tel-input theming previously scoped to
   that dialog now lives under `.financing-hub__field .iti` instead (see
   the CP-009B.1 Financing Hub section below), since the Financing Hub page
   is the only surface using that field now. --- */

.financing-cta--product {
	margin-bottom: var(--wp--preset--spacing--40);
}

/* --- Commercial-expansion pass: compact PDP installment entry + details
   modal trigger when the product has a resolvable financing profile. --- */

.financing-summary[hidden] {
	display: none;
}

.financing-summary {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	/* Pre-client polish: this referenced a "10" spacing step that the
	   theme's generated scale never defines (confirmed live —
	   getComputedStyle(document.body).getPropertyValue('--wp--preset--
	   spacing--10') is empty on the real site), so `gap` silently fell back
	   to its initial value (0) and, combined with flex discarding the
	   whitespace-only text nodes between these three items, rendered as
	   "Financiamento CredphoneConsultar opções + info" with no visible
	   space at all. "20" is the smallest step the scale actually generates. */
	gap: var(--wp--preset--spacing--20);
	margin-bottom: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm, 0.9rem);
}

.financing-summary__label {
	font-weight: 600;
}

.financing-summary__info {
	font-size: inherit;
	text-decoration: underline;
	padding: 0;
}

.financing-pdp-modal__cash-price {
	margin-bottom: var(--wp--preset--spacing--20);
}

/* --- Modal "+ detalhes" reformulado: experiência específica da PDP, não
   uma versão comprimida da calculadora central (brief §7) — lista compacta
   de opções reais em vez do fluxo genérico entrada→frequência→prazo→
   simular→resultado único. --- */

.financing-pdp-modal__entry-fixed {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-weight: 600;
}

/* The frequency <select> stays in the markup (JS toggles [hidden] when the
   product only has one supported frequency) — its label must disappear
   alongside it, not float above nothing. */
.financing-pdp-modal label[for="fpm-frequency"]:has(+ select[hidden]) {
	display: none;
}

.financing-pdp-modal__options {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--10, 4px);
	margin: 0 0 var(--wp--preset--spacing--30);
	padding: 0;
	list-style: none;
}

.financing-pdp-modal__option-btn {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	background: var(--wp--preset--color--paper);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 20%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	font: inherit;
	text-align: left;
	cursor: pointer;
}

.financing-pdp-modal__option-btn:disabled {
	cursor: default;
	opacity: 0.5;
}

.financing-pdp-modal__option-btn[aria-pressed="true"] {
	border-color: var(--wp--preset--color--brand-gold-700);
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 12%, var(--wp--preset--color--paper));
}

.financing-pdp-modal__option-btn:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 2px;
}

.financing-pdp-modal__option-term {
	font-weight: 600;
}

.financing-pdp-modal__option-value {
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.financing-pdp-modal__unavailable-message {
	margin: 0 0 var(--wp--preset--spacing--30);
}

.financing-pdp-modal [data-fpm-whatsapp-primary] {
	display: flex;
	width: 100%;
	justify-content: center;
	margin-bottom: var(--wp--preset--spacing--20);
}

.financing-pdp-modal__contact-link {
	display: block;
	width: 100%;
	text-align: center;
}

.financing-pdp-modal [data-fpm-continue-btn] {
	width: 100%;
}

/* --- CP-008.2: esconder controlos/placeholders de funcionalidades ainda não
   disponíveis (wishlist sem implementação real) em vez de os mostrar
   desativados/"brevemente" — evita que a loja pareça por terminar. Markup
   mantido intacto para reativação rápida quando cada capacidade estiver
   real.
   CP-009B.1: `/pagamento-em-prestacoes/` agora existe e a Home/PDP linkam para uma
   página real e funcional (com estado "indisponível" honesto quando não há
   regra ativa — ver credphone_financing_available()), pelo que
   `.financing-section`, `.hero__cta-financing` e `.product-summary__financing`
   saíram desta lista. `.product-card__financing`/`.benefit-item--financing`
   continuam ocultos: são um selo "Financiamento disponível" que ainda
   sobre-reclamaria disponibilidade numérica enquanto a tabela de taxas do
   operador estiver vazia (ver docs/financing-hub.md). --- */
.product-card__financing,
.product-card__wishlist,
.product-summary__wishlist,
.benefit-item--financing {
	display: none;
}

/* --- CP-010: CTA WhatsApp flutuante (project.md §24). Fixo no canto
   inferior direito; ausente do DOM quando não configurado (ver
   credphone-core.php). Único elemento fixo no rodapé do ecrã no site
   inteiro — o header sticky (acima) é o único outro elemento fixo/sticky. --- */

.whatsapp-floating {
	position: fixed;
	right: var(--wp--preset--spacing--40);
	bottom: calc(var(--wp--preset--spacing--40) + env(safe-area-inset-bottom, 0px));
	z-index: 30;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--wp--preset--spacing--20);
	min-height: 44px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
	border-radius: var(--wp--custom--radius--md);
	background: var(--wp--preset--color--brand-gold);
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
	font-weight: 600;
	text-decoration: none;
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
	/* One combined declaration: hover/active only ever change `filter`,
	   `.whatsapp-floating--hidden` only ever changes opacity/visibility — a
	   second `transition` rule on that class would replace this one instead
	   of adding to it, silently dropping the hover/active transition. */
	transition: filter 150ms ease, opacity 150ms ease, visibility 150ms ease;
}

.whatsapp-floating:hover {
	filter: brightness(0.93);
}

.whatsapp-floating:active {
	filter: brightness(0.87);
}

/* Footer-collision state (whatsapp-floating.js): visibility is required
   alongside opacity/pointer-events so the button also leaves the Tab order
   while hidden — opacity/pointer-events alone still allow keyboard focus. */
.whatsapp-floating--hidden {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

/* CP-038: the scroll control uses the project's real mobile breakpoint and
   sits in the same right-side utility stack as WhatsApp, one restrained
   control-height above it. Desktop/tablet-desktop layouts never render it. */
.back-to-top-control {
	display: none;
}

@media (max-width: 781px) {
	.back-to-top-control {
		position: fixed;
		right: var(--wp--preset--spacing--30);
		bottom: calc(var(--wp--preset--spacing--30) + 48px + var(--wp--preset--spacing--20) + env(safe-area-inset-bottom, 0px));
		z-index: 29;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		width: 44px;
		height: 44px;
		padding: 0;
		background: var(--wp--preset--color--paper);
		color: var(--wp--preset--color--ink);
		border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 18%, transparent);
		border-radius: var(--wp--custom--radius--md);
		box-shadow: 0 2px 8px color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
		cursor: pointer;
	}

	.back-to-top-control[hidden] {
		display: none;
	}

	.back-to-top-control.is-probing {
		pointer-events: none;
	}

	.back-to-top-control:hover {
		background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 10%, var(--wp--preset--color--paper));
		border-color: color-mix(in srgb, var(--wp--preset--color--brand-gold) 45%, transparent);
	}

	.back-to-top-control:focus-visible {
		outline: 2px solid var(--wp--preset--color--brand-gold-700);
		outline-offset: 2px;
	}

	.back-to-top-control__icon {
		font-size: 1.25rem;
		font-weight: 600;
		line-height: 1;
		transform: translateY(-1px);
	}
}

/* Gate 5: below ~781px the full-width text pill sat on top of whatever
   content scrolled underneath it (confirmed live: it covered the Home
   financing banner's heading/lead text). Compact, icon-only, still a real
   44x44+ target; the label stays in the accessibility tree via the
   visually-hidden span, not aria-label alone. */
@media (max-width: 781px) {
	.whatsapp-floating {
		right: var(--wp--preset--spacing--30);
		bottom: calc(var(--wp--preset--spacing--30) + env(safe-area-inset-bottom, 0px));
		width: 48px;
		height: 48px;
		min-height: 48px;
		padding: 0;
		border-radius: 50%;
	}

	.whatsapp-floating__label {
		position: absolute;
		width: 1px;
		height: 1px;
		padding: 0;
		margin: -1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		white-space: nowrap;
		border: 0;
	}
}

/* --- Envio/levantamento + confiança --- */

.product-summary__shipping {
	margin-bottom: var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 75%, var(--wp--preset--color--paper));
}

.product-summary__trust {
	margin-bottom: var(--wp--preset--spacing--50);
}

/* --- Metadata (SKU/categoria/tags) — discreto, resolve o aspeto "raw" --- */

.product-summary__meta {
	padding-top: var(--wp--preset--spacing--40);
	border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 60%, var(--wp--preset--color--paper));
}

.product-summary__meta .wp-block-group {
	gap: var(--wp--preset--spacing--40) !important;
	flex-wrap: wrap;
}

.product-summary__meta a {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 2px;
}

/* --- Tabs (descrição / informação adicional / avaliações) --- */

.product-tabs {
	margin-bottom: var(--wp--preset--spacing--70);
}

.product-tabs ul.tabs {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--60);
	margin: 0 0 var(--wp--preset--spacing--50);
	padding: 0 0 var(--wp--preset--spacing--30);
	list-style: none;
	border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
}

.product-tabs ul.tabs li a {
	color: color-mix(in srgb, var(--wp--preset--color--ink) 60%, var(--wp--preset--color--paper));
	text-decoration: none;
	font-weight: 600;
}

.product-tabs ul.tabs li.active a,
.product-tabs ul.tabs li a:hover,
.product-tabs ul.tabs li a:focus-visible {
	color: var(--wp--preset--color--ink);
}

.product-tabs .woocommerce-Tabs-panel {
	max-width: 72ch;
}

.product-tabs #commentform input:not([type="submit"]):not([type="checkbox"]),
.product-tabs #commentform textarea,
.product-tabs #commentform select {
	box-sizing: border-box;
	width: 100%;
	min-height: 44px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	margin-top: var(--wp--preset--spacing--20);
	background: var(--wp--preset--color--paper);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	font-family: var(--wp--preset--font-family--inter);
}

.product-tabs #commentform .submit {
	min-height: 44px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
	background: var(--wp--preset--color--brand-gold);
	border: 1px solid var(--wp--preset--color--brand-gold);
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--preset--color--ink);
	font-weight: 600;
	cursor: pointer;
}

/* --- Produtos relacionados (grelha reaproveita .credphone-shop-grid) --- */

.related-products {
	margin-bottom: var(--wp--preset--spacing--70);
}

.related-products__heading {
	margin-bottom: var(--wp--preset--spacing--40);
}

@media (max-width: 781px) {
	.product-hero {
		gap: var(--wp--preset--spacing--50) !important;
	}

	.product-summary__wishlist {
		position: static;
		margin-bottom: var(--wp--preset--spacing--20);
	}

	.product-summary__title {
		margin-inline-end: 0;
	}
}

/* =========================================================
   Carrinho e Checkout (CP-008)
   Blocos nativos WooCommerce Cart/Checkout Blocks — layout,
   comportamento nativo (quantidade, remover, cupão, validação,
   estados de shipping/payment em falta) intocados. Reutiliza
   .btn, .icon-btn, .form-input, .notice, .price e os tokens do
   theme.json sempre que possível. Seletores contra classes do
   WooCommerce confirmados no HTML real renderizado pelo wp-env
   (WooCommerce 11.0.1, Cart/Checkout Blocks) e/ou no código-fonte
   do plugin, não adivinhados.

   O Checkout usa um template próprio do tema
   (templates/page-checkout.html + parts/checkout-header.html +
   parts/checkout-footer.html) em vez do template genérico
   page.html, porque o WooCommerce fornece o seu próprio
   page-checkout.html com um header "distraction free" (só nome
   do site + link do carrinho, sem navegação) e sem footer —
   comportamento nativo alinhado com o project.md §14 ("checkout
   sem navegação distrativa excessiva"). O nosso template
   substitui apenas a marca (logótipo em vez de texto) e adiciona
   um rodapé mínimo, mantendo o mesmo espírito.
   ========================================================= */

/* --- Header do Checkout (distraction free, com logótipo) --- */

/* CP-019: previously stayed on the light `.site-header` default — read as a
   generic, unbranded white bar next to the dark header on every other page.
   Now matches the main commerce header's dark surface (same logo asset,
   already a white+gold mark proven legible on dark — no new asset needed);
   still distraction-free (no nav/search/category menu), just visually
   consistent with the rest of the store. */
.site-header--checkout {
	background: var(--wp--custom--surface--inverse);
	color: var(--wp--custom--text--on-inverse);
	border-bottom: 1px solid var(--wp--custom--border--on-inverse);
}

.site-header--checkout .site-header__row--checkout {
	padding-block: var(--wp--preset--spacing--40);
}

.site-logo--checkout img {
	height: 40px;
}

.checkout-cart-link {
	min-width: auto;
	min-height: auto;
	padding: 0;
	background: transparent;
}

.checkout-cart-link .wc-block-cart-link {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	min-height: 44px;
	padding-inline: var(--wp--preset--spacing--30);
	border-radius: var(--wp--custom--radius--sm);
	color: var(--wp--custom--text--on-inverse);
	text-decoration: none;
	transition: background-color 150ms ease, color 150ms ease;
}

.checkout-cart-link .wc-block-cart-link:hover {
	background: var(--wp--preset--color--brand-gold);
	color: var(--wp--preset--color--ink);
}

.site-header--checkout a:focus-visible,
.site-header--checkout button:focus-visible {
	outline-color: var(--wp--preset--color--brand-gold);
}

.checkout-cart-link .wc-block-mini-cart__icon {
	width: 20px;
	height: 20px;
}

.checkout-cart-link .wc-block-cart-link__text {
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
}

/* --- Rodapé mínimo do Checkout --- */

.site-footer--checkout {
	margin-top: 0;
}

.site-footer--checkout .site-footer__checkout-row {
	align-items: center;
	padding-block: var(--wp--preset--spacing--50);
	border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
	gap: var(--wp--preset--spacing--30);
}

.site-footer--checkout .footer-copyright {
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
}

.footer-list--inline {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40);
	margin: 0;
	padding: 0;
	font-size: var(--wp--preset--font-size--sm);
}

.footer-list--inline a {
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
}

.footer-list--inline a:hover {
	color: var(--wp--preset--color--brand-gold-700);
}

/* --- Título da página (Carrinho / Finalizar compra) --- */

.site-main .wp-block-post-title {
	margin-bottom: var(--wp--preset--spacing--50);
}

/* --- Layout partilhado: sidebar de totais (Carrinho e Checkout) --- */

.wc-block-cart .wc-block-components-sidebar-layout,
.wc-block-checkout .wc-block-components-sidebar-layout {
	align-items: start;
}

.wc-block-cart__sidebar,
.wc-block-checkout__sidebar {
	background: var(--wp--preset--color--paper);
	border: var(--wp--custom--elevation--border);
	border-radius: var(--wp--custom--radius--md);
	padding: var(--wp--preset--spacing--50);
}

.wc-block-components-order-summary__title,
.wc-block-cart-order-summary-heading-block .wc-block-components-title {
	margin-bottom: var(--wp--preset--spacing--30);
}

.wc-block-components-totals-item {
	padding-block: var(--wp--preset--spacing--20);
}

.wc-block-components-totals-item__value {
	font-variant-numeric: tabular-nums;
}

.wc-block-components-totals-footer-item {
	margin-top: var(--wp--preset--spacing--30);
	padding-top: var(--wp--preset--spacing--30);
	border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
}

.wc-block-checkout .wc-block-components-totals-wrapper:has(> .wc-block-components-totals-footer-item),
.wc-block-checkout .wc-block-components-totals-footer-item {
	border-top: 0;
}

.wc-block-components-totals-footer-item .wc-block-components-totals-item__label,
.wc-block-components-totals-footer-item .wc-block-components-totals-item__value {
	font-weight: 700;
	font-size: var(--wp--preset--font-size--lg);
}

/* --- Cupão (painel colapsável nativo) --- */

.wc-block-components-panel__button {
	padding-block: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	color: var(--wp--preset--color--ink);
	cursor: pointer;
}

.wc-block-components-totals-coupon__form {
	display: flex;
	gap: var(--wp--preset--spacing--20);
	margin-top: var(--wp--preset--spacing--20);
}

.wc-block-components-totals-coupon__input {
	flex: 1;
	min-width: 0;
}

.wc-block-components-totals-coupon__input input {
	box-sizing: border-box;
	width: 100%;
	min-height: 44px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
}

.wc-block-components-totals-coupon__input input:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 1px;
	border-color: var(--wp--preset--color--brand-gold-700);
}

/* Commercial-expansion pass: the previous transparent-background default
   read as unreadable against the page background (only the 1px border was
   visible). Default is now a solid dark/black fill with white text — the
   hover state inverts to white/black, matching the explicit contrast
   contract for this ONE control (checkout/cart "Aplicar cupão" action) —
   not a sitewide `.btn` restyle. This button also carries Woo's own
   `.wc-block-components-button.contained` classes (shared with "Avançar
   para o checkout"/"Finalizar encomenda"), whose OWN hover rule
   (`color-mix(ink 85%, brand-gold)`, below) has equal selector specificity
   and sits later in source order, so it would otherwise win regardless —
   the `.contained` qualifier here is required, not decorative, to keep
   this control's hover on the explicit white/black contract instead of
   inheriting that generic gold-tinted hover. */
.wc-block-components-totals-coupon__form .wc-block-components-totals-coupon__button.contained {
	min-height: 44px;
	padding-inline: var(--wp--preset--spacing--40);
	border-radius: var(--wp--custom--radius--sm);
	border: 1px solid var(--wp--preset--color--ink);
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--paper);
	font-weight: 600;
	cursor: pointer;
}

/* The extra `.wc-block-components-totals-coupon__form` ancestor qualifier
   is required, not decorative: `.contained:hover` alone ties EXACTLY on
   specificity with the generic "Proceed to Checkout"/"Place Order" hover
   rule below (both resolve to 4 class-level selectors), so the later one
   in source order silently won regardless of which came first here —
   confirmed live on staging (the gold-tinted generic hover was rendering
   instead of this white/black one until this extra qualifier was added). */
.wc-block-components-totals-coupon__form .wc-block-components-totals-coupon__button.contained:hover:not(:disabled) {
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border-color: var(--wp--preset--color--ink);
}

.wc-block-components-totals-coupon__form .wc-block-components-totals-coupon__button.contained:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 1px;
}

/* --- Botões nativos de ação (Proceed to Checkout / Place Order) --- */

.wc-block-components-button.contained {
	border-radius: var(--wp--custom--radius--sm);
	background: var(--wp--preset--color--ink);
	min-height: 44px;
	font-weight: 600;
}

.wc-block-components-button.contained:hover:not(:disabled) {
	background: color-mix(in srgb, var(--wp--preset--color--ink) 85%, var(--wp--preset--color--brand-gold));
}

.wc-block-components-button.contained:active:not(:disabled) {
	background: color-mix(in srgb, var(--wp--preset--color--ink) 85%, black);
}

/* Side-cart (mini-cart drawer) empty-state CTA only — this control never
   carries `.contained`, so it fell through to WooCommerce Blocks' own
   near-square default instead of either `--radius--sm` (other native Woo
   action buttons) or `--radius--md` (`.btn`). PO asked specifically for a
   pill here; scoped to this one selector so it doesn't change any other
   `.wc-block-components-button`. */
.wc-block-mini-cart__shopping-button {
	border-radius: var(--wp--custom--radius--pill);
}

/* --- Carrinho: tabela de itens --- */

.wc-block-cart-items {
	width: 100%;
	border-collapse: collapse;
}

.wc-block-cart-items__header th {
	padding-block: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
	text-align: left;
}

.wc-block-cart-items__row {
	border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
}

.wc-block-cart-items__row td {
	padding-block: var(--wp--preset--spacing--40);
	vertical-align: top;
}

.wc-block-cart-item__image img {
	display: block;
	border-radius: var(--wp--custom--radius--sm);
	border: var(--wp--custom--elevation--border);
	background: var(--wp--preset--color--paper);
}

/* Root cause of the duplicate cart/mini-cart thumbnail (CP-016 human report):
   Woo's Interactivity API renders TWO <img> per row in this cell — one kept
   server-side `hidden` for the "product hidden from catalog" state, one the
   real visible image inside an <a>. Author-origin `display: block` above
   beats the UA stylesheet's `[hidden] { display: none }` regardless of
   specificity (UA rules are always lowest-priority), so both painted. */
.wc-block-cart-item__image img[hidden] {
	display: none;
}

.wc-block-components-product-name {
	font-weight: 600;
	color: var(--wp--preset--color--ink);
	text-decoration: none;
}

.wc-block-components-product-name:hover {
	color: var(--wp--preset--color--brand-gold-700);
}

.wc-block-cart-item__prices,
.wc-block-cart-item__total {
	font-variant-numeric: tabular-nums;
}

.wc-block-cart-item__product .wc-block-components-product-price,
.wc-block-components-order-summary-item__individual-prices {
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 400;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
}

.wc-block-components-order-summary-item {
	flex-wrap: wrap;
}

.wc-block-components-product-metadata {
	margin-top: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
}

.wc-block-cart-item__quantity {
	margin-top: var(--wp--preset--spacing--30);
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--30);
}

.wc-block-components-quantity-selector {
	display: inline-flex;
	align-items: stretch;
	height: 46px;
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	overflow: hidden;
}

.wc-block-components-quantity-selector__button {
	min-width: 36px;
	background: transparent;
	border: none;
	color: var(--wp--preset--color--ink);
	cursor: pointer;
	font-size: var(--wp--preset--font-size--base);
}

.wc-block-components-quantity-selector__button:hover:not(:disabled) {
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 25%, transparent);
}

.wc-block-components-quantity-selector__input {
	box-sizing: border-box;
	width: 44px;
	border: none;
	border-inline: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 20%, transparent);
	text-align: center;
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
	color: var(--wp--preset--color--ink);
	background: transparent;
}

.wc-block-cart-item__remove-link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding-inline: var(--wp--preset--spacing--20);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
	font-size: var(--wp--preset--font-size--sm);
	text-decoration: underline;
	text-underline-offset: 2px;
	cursor: pointer;
}

.wc-block-cart-item__remove-link:hover {
	color: var(--wp--preset--color--error);
}

/* --- Carrinho: estado vazio (CP-028) --- */

/* Content is real page content (bin/content/setup-empty-cart-content.php),
   not theme markup — only rendered by WooCommerce Blocks when the cart is
   genuinely empty, so none of this can affect the populated-cart layout.
   A soft, low-opacity border + shadow instead of this site's usual hard
   1px-solid-ink `.card` border — deliberately more "premium surface" than
   "generic bordered box" for this one hero-like moment, per brief. */
.credphone-empty-cart {
	max-width: 640px;
	margin-inline: auto;
	padding: var(--wp--preset--spacing--70) var(--wp--preset--spacing--50);
	text-align: center;
	background: var(--wp--preset--color--paper);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 7%, transparent);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: var(--wp--custom--elevation--raised);
}

@media (max-width: 599px) {
	.credphone-empty-cart {
		padding: var(--wp--preset--spacing--60) var(--wp--preset--spacing--40);
	}
}

/* The brief's "pequeno detalhe amarelo opcional" lives on the tile's own
   ring (an inset gold hairline) rather than the icon glyph itself — the
   Phosphor bag icon is a single <path>, so there's no bag-handle sub-path
   to color separately without hand-editing the (unmodified, verbatim)
   source SVG. */
.credphone-empty-cart__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 80px;
	height: 80px;
	margin-bottom: var(--wp--preset--spacing--40);
	border-radius: var(--wp--custom--radius--lg);
	background: color-mix(in srgb, var(--wp--preset--color--ink) 4%, var(--wp--preset--color--paper));
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 8%, transparent);
	box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--wp--preset--color--brand-gold) 35%, transparent);
	color: var(--wp--preset--color--ink);
}

.credphone-empty-cart__icon svg {
	width: 34px;
	height: 34px;
}

.credphone-empty-cart .wc-block-cart__empty-cart__title {
	margin: 0;
}

.credphone-empty-cart .empty-cart-subtext {
	max-width: 40ch;
	margin: var(--wp--preset--spacing--20) auto 0;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
}

.credphone-empty-cart__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--wp--preset--spacing--20);
	margin-top: var(--wp--preset--spacing--50);
}

@media (max-width: 430px) {
	.credphone-empty-cart__actions {
		flex-direction: column;
	}

	.credphone-empty-cart__actions .btn {
		width: 100%;
	}
}

.credphone-empty-cart__trust {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--wp--preset--spacing--40);
	margin: var(--wp--preset--spacing--60) 0 0;
	padding-top: var(--wp--preset--spacing--50);
	border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 8%, transparent);
}

.credphone-empty-cart__trust li {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 70%, var(--wp--preset--color--paper));
}

.credphone-empty-cart__trust svg {
	flex-shrink: 0;
	width: 18px;
	height: 18px;
	color: var(--wp--preset--color--brand-gold-700);
}

@media (max-width: 430px) {
	.credphone-empty-cart__trust {
		flex-direction: column;
		align-items: center;
		gap: var(--wp--preset--spacing--20);
	}
}

.empty-cart-discovery {
	margin-top: var(--wp--preset--spacing--80);
	max-width: 100%;
}

.empty-cart-discovery .section-heading {
	text-align: center;
	margin-inline: auto;
}

.empty-cart-discovery .section-heading__eyebrow {
	justify-content: center;
}

.wc-block-grid__products {
	margin-inline: 0;
}

.wc-block-grid__product {
	background: var(--wp--preset--color--paper);
	border: var(--wp--custom--elevation--border);
	border-radius: var(--wp--custom--radius--md);
	padding: var(--wp--preset--spacing--40);
}

.wc-block-grid__product-title {
	font-weight: 600;
	color: var(--wp--preset--color--ink);
	margin-top: var(--wp--preset--spacing--30);
}

.wc-block-grid__product-price {
	font-variant-numeric: tabular-nums;
}

/* --- Checkout: steps do formulário --- */

.wc-block-components-checkout-step {
	padding-block: var(--wp--preset--spacing--50);
	border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
}

.wc-block-components-checkout-step:first-child {
	padding-top: 0;
}

.wc-block-components-checkout-step:last-child {
	border-bottom: none;
}

.wc-block-components-checkout-step__title {
	font-size: var(--wp--preset--font-size--lg);
	margin-bottom: var(--wp--preset--spacing--30);
}

/* --- Checkout: campos --- */

.wc-block-components-text-input {
	margin-bottom: var(--wp--preset--spacing--30);
}

.wc-block-components-text-input input,
.wc-block-components-address-form select,
.wc-block-components-select-input select {
	box-sizing: border-box;
	width: 100%;
	min-height: 44px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
}

.wc-block-components-text-input input:focus-visible,
.wc-block-components-address-form select:focus-visible,
.wc-block-components-select-input select:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 1px;
	border-color: var(--wp--preset--color--brand-gold-700);
}

/* --- Checkout: pagamento (Stripe Payment Element / Klarna) ---
   O plugin oficial WooCommerce Stripe Gateway deteta sozinho se deve usar o
   tema "stripe" (claro) ou "night" (escuro) para o Payment Element,
   percorrendo `document.querySelector` (global, não `closest()`) por uma
   lista fixa de seletores — #payment-method, form.wc-block-checkout__form,
   .wc-block-checkout, main, .wp-block-group, .entry-content, .site-content,
   body — à procura do primeiro com background-color não transparente.
   Sem esta regra, nenhum seletor antes de `.wp-block-group` tem cor de
   fundo explícita, e esse seletor apanha o cabeçalho escuro do site
   (var(--wp--preset--color--ink), #171717) por ser o primeiro
   `.wp-block-group` do documento — o plugin conclui que a página é escura
   e pinta todo o Payment Element (incl. Klarna) de preto sobre um checkout
   claro. Isto só torna explícito o branco que já é o fundo visual real do
   checkout, no seletor de maior prioridade da lista. */
#payment-method {
	background-color: var(--wp--preset--color--paper);
}

/* --- Checkout: avisos nativos de shipping/payment em falta --- */

.wc-block-components-notice-banner {
	display: flex;
	gap: var(--wp--preset--spacing--30);
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--50);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
	border-left: 4px solid var(--wp--preset--color--info);
	border-radius: var(--wp--custom--radius--sm);
	background: var(--wp--preset--color--paper);
}

.wc-block-components-notice-banner.is-error {
	border-left-color: var(--wp--preset--color--error);
}

.wc-block-components-notice-banner.is-warning {
	border-left-color: var(--wp--preset--color--warning);
}

/* --- Checkout: termos e ação final --- */

.wc-block-checkout__terms {
	margin-top: var(--wp--preset--spacing--40);
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
}

.wc-block-checkout__terms a {
	color: var(--wp--preset--color--ink);
}

.wc-block-checkout__terms-checkbox-wrapper {
	display: flex;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--20);
}

/* --- Responsivo (abaixo de 782px, mesmo ponto de quebra do resto do tema) --- */

@media (max-width: 781px) {
	.wc-block-cart-items {
		table-layout: fixed;
	}

	.wc-block-cart-item__image {
		width: 64px;
	}

	.wc-block-cart-item__total {
		width: 84px;
	}

	.wc-block-cart__sidebar,
	.wc-block-checkout__sidebar {
		padding: var(--wp--preset--spacing--40);
	}

	.site-header__row--checkout {
		padding-block: var(--wp--preset--spacing--30);
	}

	.site-logo--checkout img {
		height: 36px;
	}

	body.woocommerce-checkout .site-main {
		margin-top: 0;
		padding-top: var(--wp--preset--spacing--50);
	}

	.site-footer--checkout .site-footer__checkout-row {
		flex-direction: column;
		align-items: flex-start;
		gap: var(--wp--preset--spacing--20);
	}
}

/* =========================================================
   My Account shell (CP-008.1 Account-shell polish)

   The page.html template (shared with every other generic content
   page — Sobre, Contactos, FAQ, etc.) previously gave My Account zero
   dedicated treatment: native WooCommerce markup rendered with no
   card/spacing/hierarchy language of its own. Every rule below is
   scoped to WooCommerce's own body classes for the My Account
   endpoints (confirmed in the real rendered page, not guessed —
   woocommerce-account, woocommerce-dashboard, woocommerce-orders,
   woocommerce-downloads, woocommerce-edit-address,
   woocommerce-edit-account), never touching the shared page.html
   template or any Shop/Product/Cart/Checkout selector. Native Woo
   markup/behavior/endpoints are untouched — styling only.
   ========================================================= */

body.woocommerce-account .site-main {
	min-height: 0;
}

body.woocommerce-account .wp-block-post-title {
	margin-bottom: var(--wp--preset--spacing--30);
}

/* The classic login template's own <h2> ("Iniciar sessão"), directly
   before the form — quieter than the page title so the two don't
   compete for the same weight. */
body.woocommerce-account .woocommerce > h2:first-child {
	font-size: var(--wp--preset--font-size--lg);
	margin-bottom: var(--wp--preset--spacing--30);
}

body.woocommerce-account .woocommerce-form-login,
body.woocommerce-account .woocommerce-form-register,
body.woocommerce-account .woocommerce-ResetPassword,
body.woocommerce-account .woocommerce-EditAccountForm {
	box-sizing: border-box;
	max-width: 460px;
	background: var(--wp--preset--color--paper);
	border: var(--wp--custom--elevation--border);
	border-radius: var(--wp--custom--radius--md);
	padding: var(--wp--preset--spacing--50);
}

/* CP-030: registration is now enabled (was off, so `#customer_login` never
   rendered its own col2-set wrapper before — WooCommerce's classic
   template only prints it when both forms exist). Two balanced columns on
   desktop, stacked on mobile at the same breakpoint this block already
   uses for the logged-in shell below. Each column keeps the login/
   register card treatment above at its own natural width instead of
   stretching to 460px each. */
body.woocommerce-account #customer_login.col2-set {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--wp--preset--spacing--60);
	align-items: start;
}

/* Same root cause CP-029 already found and fixed once on the PDP
   add-to-cart form: WooCommerce core's own float-era clearfix
   (`.col2-set::before/::after { content: " "; display: table }`,
   0,0,2,1 specificity) generates two REAL grid items once this element
   becomes a grid container — confirmed live: with them still generating
   content, `.col-1`("Login") landed in row 1 column 2 and
   `.col-2`("Register") landed in row 2 column 1 instead of side by side,
   because the grid's first cell went to `::before`. `content: none` here
   (0,0,3,1, beating the clearfix rule) removes them from generating any
   box at all, exactly like the PDP fix. */
body.woocommerce-account #customer_login.col2-set::before,
body.woocommerce-account #customer_login.col2-set::after {
	content: none;
}

/* WooCommerce core's own `.col2-set .col-1/.col-2` rule (float:left/right
   + width:48%) still sets a definite width on these grid items even
   though float itself is a no-op on a grid item — an explicit width wins
   over the default `justify-self: stretch` (confirmed live: both columns
   rendered at 48% of their 1fr track, ~176px of a 366px track). This ID-
   anchored selector outranks that core rule's class-only specificity
   regardless of source order. */
body.woocommerce-account #customer_login.col2-set .col-1,
body.woocommerce-account #customer_login.col2-set .col-2 {
	float: none;
	width: 100%;
}

body.woocommerce-account #customer_login.col2-set .woocommerce-form-login,
body.woocommerce-account #customer_login.col2-set .woocommerce-form-register {
	max-width: none;
	width: 100%;
	margin: 0;
}

/* Exactly one gold/primary submit per card: the form's own submit button.
   Any other button-like control sharing a view (e.g. a "Perdeu a senha?"
   link is already a plain text link, not a button, so no conflict there)
   gets the neutral/outlined secondary treatment instead of a second gold
   CTA competing for attention. */
body.woocommerce-account .woocommerce-form-login__submit,
body.woocommerce-account .woocommerce-form-register__submit,
body.woocommerce-account .woocommerce-EditAccountForm button[type="submit"],
body.woocommerce-account .woocommerce-ResetPassword button[type="submit"],
body.woocommerce-account .woocommerce-address-fields button[type="submit"] {
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
	border: 1px solid var(--wp--preset--color--brand-gold);
	border-radius: var(--wp--custom--radius--md);
	background: var(--wp--preset--color--brand-gold);
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
	font-weight: 600;
	line-height: 1.2;
	cursor: pointer;
	transition: filter 150ms ease;
}

body.woocommerce-account .woocommerce-form-login__submit:hover,
body.woocommerce-account .woocommerce-form-register__submit:hover,
body.woocommerce-account .woocommerce-EditAccountForm button[type="submit"]:hover,
body.woocommerce-account .woocommerce-ResetPassword button[type="submit"]:hover,
body.woocommerce-account .woocommerce-address-fields button[type="submit"]:hover {
	filter: brightness(0.93);
}

/* Any secondary/neutral button that shares a My Account view with one of
   the primary submits above (e.g. an address book's own "Cancelar" link
   rendered as `.button`) — outlined, not a second gold fill. A single
   `:not()` with a selector list (not two chained `:not()`s) is
   deliberate: per spec its specificity is the MOST specific argument, not
   the sum, which keeps this rule's specificity (3 classes, 1 type) below
   the primary submit rules above (3 classes, 2 types) — confirmed live
   that two chained `:not()`s summed to 4 classes and actually WON over
   the primary rule for `.woocommerce-EditAccountForm button[type=submit]`
   (3 classes, 2 types), leaving "Save changes" transparent instead of
   gold. */
body.woocommerce-account .button:not(.woocommerce-form-login__submit, .woocommerce-form-register__submit) {
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
	background: transparent;
	border: 1px solid var(--wp--preset--color--ink);
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
	font-weight: 600;
	line-height: 1.2;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 150ms ease, color 150ms ease;
}

body.woocommerce-account .button:not(.woocommerce-form-login__submit, .woocommerce-form-register__submit):hover {
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--paper);
}

body.woocommerce-account .woocommerce-form-row {
	/* Woo's default .form-row-first/-last (47% width, meant for a
	   side-by-side register/login pair) has no sibling row on any of
	   these single-field forms — full width avoids the label
	   wrapping awkwardly once the card is narrower than the old
	   unstyled full-width layout. */
	width: 100%;
	margin-bottom: var(--wp--preset--spacing--30);
}

body.woocommerce-account .woocommerce-form-login__rememberme {
	margin-bottom: var(--wp--preset--spacing--30);
}

body.woocommerce-account .woocommerce-LostPassword {
	margin: var(--wp--preset--spacing--30) 0 0;
}

/* Native inputs reuse the shared .form-input treatment (44px touch
   target, brand-gold focus-visible) instead of the browser-default
   look they had before. Scoped here rather than added to the shared
   .form-input selector because .woocommerce-Input also appears on
   Checkout, which this pass must not touch. */
body.woocommerce-account .woocommerce-Input {
	box-sizing: border-box;
	display: block;
	width: 100%;
	min-height: 44px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--base);
}

body.woocommerce-account .woocommerce-Input:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 1px;
	border-color: var(--wp--preset--color--brand-gold-700);
}

/* Woo's password button is already a semantic type="button" with a dynamic
   accessible name and keyboard behavior, but its core CSS collapses the hit
   area to the 22px eye pseudo-element. Keep that icon size/alignment while
   giving the actual interactive element the project's 44px touch target. */
body.woocommerce-account .password-input .woocommerce-Input {
	padding-right: 3.5rem;
}

body.woocommerce-account .password-input .show-password-input {
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	right: 0;
	border-radius: var(--wp--custom--radius--sm);
}

body.woocommerce-account .password-input .show-password-input:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 1px;
}

body.woocommerce-account .password-input .show-password-input::before {
	flex: 0 0 22px;
}

/* Notices: this My Account login/lost-password flow renders errors via
   the Blocks store-notice component (.wc-block-components-notice-banner),
   not the classic .woocommerce-error list (confirmed in the live DOM,
   not assumed) — its border-left/background already resolve to this
   project's exact error/success/info tokens, so only the width needs
   aligning with the card below it (was full site-main width, ~768px,
   against a 510px card). Scoped to body.woocommerce-account because the
   same component also appears in Cart/Checkout Store API errors, which
   this pass must not touch. */
body.woocommerce-account .wc-block-components-notice-banner {
	max-width: 460px;
	margin-bottom: var(--wp--preset--spacing--40);
}

/* Logged-in dashboard/orders/downloads/addresses/edit-account: nav +
   content as a two-column shell instead of a bare stacked list. */
body.woocommerce-dashboard .woocommerce,
body.woocommerce-orders .woocommerce,
body.woocommerce-downloads .woocommerce,
body.woocommerce-edit-address .woocommerce,
body.woocommerce-edit-account .woocommerce {
	display: flex;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--60);
}

.woocommerce-MyAccount-navigation {
	box-sizing: border-box;
	flex: 0 0 220px;
	background: var(--wp--preset--color--paper);
	border: var(--wp--custom--elevation--border);
	border-radius: var(--wp--custom--radius--md);
	padding: var(--wp--preset--spacing--30);
}

.woocommerce-MyAccount-content {
	flex: 1 1 auto;
	min-width: 0;
	max-width: 620px;
}

.woocommerce-MyAccount-navigation ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
}

.woocommerce-MyAccount-navigation-link a {
	display: block;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	border-radius: var(--wp--custom--radius--sm);
	color: var(--wp--preset--color--ink);
	text-decoration: none;
	border-left: 3px solid transparent;
}

.woocommerce-MyAccount-navigation-link a:hover {
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 12%, transparent);
}

.woocommerce-MyAccount-navigation-link.is-active a {
	font-weight: 700;
	border-left-color: var(--wp--preset--color--brand-gold-700);
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 8%, transparent);
}

@media (max-width: 600px) {
	body.woocommerce-dashboard .woocommerce,
	body.woocommerce-orders .woocommerce,
	body.woocommerce-downloads .woocommerce,
	body.woocommerce-edit-address .woocommerce,
	body.woocommerce-edit-account .woocommerce {
		flex-direction: column;
	}

	.woocommerce-MyAccount-navigation {
		flex-basis: auto;
		width: 100%;
	}

	.woocommerce-MyAccount-content {
		max-width: none;
	}

	body.woocommerce-account #customer_login.col2-set {
		grid-template-columns: 1fr;
	}
}

/* --- CP-009B.1: Financing Hub (/pagamento-em-prestacoes/) — reuses .card/.btn/
   .form-input/.notice/.badge, no new visual system introduced. --- */

.financing-hub__intro {
	margin-bottom: var(--wp--preset--spacing--50);
}

.financing-hub__title {
	margin: 0 0 var(--wp--preset--spacing--20);
}

.financing-hub__lead {
	margin: 0;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 70%, var(--wp--preset--color--paper));
}

.financing-hub {
	margin-bottom: var(--wp--preset--spacing--70);
}

.financing-hub__form {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--60);
}

.financing-hub__step-title {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--lg);
}

.financing-hub__step + .financing-hub__step {
	padding-top: var(--wp--preset--spacing--60);
	border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
}

/* CP-023 Fase 1 — progressive disclosure: a step with no resolved product
   yet is genuinely removed from layout (not just disabled/dimmed), which
   is the actual fix for the "wall of grey locked sections" complaint.
   financing-hub.js's updateGatedUI() sets this attribute; the PHP-rendered
   initial value (see financing-hub-render.php's $initial_step_state)
   avoids a flash of the wrong state before JS runs. */
.financing-hub__step[data-financing-step-state="pending"] {
	display: none;
}

.financing-hub__step[data-financing-step-state="active"] {
	animation: financing-step-reveal 220ms ease both;
}

@keyframes financing-step-reveal {
	from {
		opacity: 0;
		transform: translateY(6px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

@media (prefers-reduced-motion: reduce) {
	.financing-hub__step[data-financing-step-state="active"] {
		animation: none;
	}
}

/* Gate 3 — path chooser + guided recommender. Every `hidden`-toggled
   container below sets its own `display` for the visible state, so each
   needs the matching `[hidden]{display:none}` override — same recurring
   "author display beats the UA [hidden] rule" bug already documented
   elsewhere in this file (mini-cart, financing-hub__product-selected). */
.financing-hub__path-chooser,
.financing-hub__guided,
.financing-hub__manual-path {
	display: block;
}

.financing-hub__path-chooser[hidden],
.financing-hub__guided[hidden],
.financing-hub__manual-path[hidden] {
	display: none;
}

.financing-hub__path-chooser-lead {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-weight: 600;
}

/* CP-023 Fase 1 — path cards. DESIGN.md's global "no neon/glow/gradient"
   rule has an explicit, Product-Owner-approved LOCAL exception scoped to
   this one feature only (see docs/PROJECT_STATE.md) — every accent below
   is a local custom property derived from the already-approved brand-gold
   token via color-mix(), never a new brand color and never touching
   theme.json. Kept deliberately restrained: no dark background, no
   permanent glow, no glassmorphism — only a soft colored shadow and a
   small translateY on hover/focus, a firmer accent only once selected. */
.financing-hub__path-options {
	--financing-path-accent: var(--wp--preset--color--brand-gold);
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: var(--wp--preset--spacing--30);
}

.financing-hub__path-option {
	--path-accent: var(--financing-path-accent);
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--10);
	text-align: left;
	padding: var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--paper);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 18%, transparent);
	border-radius: var(--wp--custom--radius--md);
	cursor: pointer;
	font: inherit;
	min-height: 44px;
	transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease;
}

.financing-hub__path-option:hover,
.financing-hub__path-option:focus-visible {
	border-color: var(--path-accent);
	transform: translateY(-3px);
	box-shadow: 0 10px 22px -14px color-mix(in srgb, var(--path-accent) 55%, transparent);
}

.financing-hub__path-option:active {
	border-color: var(--path-accent);
	background: color-mix(in srgb, var(--path-accent) 10%, var(--wp--preset--color--paper));
	transform: translateY(-1px);
	box-shadow: 0 6px 16px -12px color-mix(in srgb, var(--path-accent) 60%, transparent);
}

.financing-hub__path-option-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: var(--wp--custom--radius--sm);
	background: color-mix(in srgb, var(--path-accent) 22%, transparent);
	color: color-mix(in srgb, var(--path-accent) 85%, var(--wp--preset--color--ink) 15%);
}

.financing-hub__path-option-icon svg {
	width: 22px;
	height: 22px;
}

.financing-hub__path-option-title {
	font-weight: 700;
}

.financing-hub__path-option-lead {
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, transparent);
}

@media (prefers-reduced-motion: reduce) {
	.financing-hub__path-option {
		transition: none;
	}

	.financing-hub__path-option:hover,
	.financing-hub__path-option:focus-visible,
	.financing-hub__path-option:active {
		transform: none;
	}
}

/* Mobile-first (390px primary viewport, CP-023 Fase 1 §10): 3 stacked
   cards must stay contained, never 3 tall marketing blocks — smaller
   padding/gap only, layout (icon above title/lead) unchanged. */
@media (max-width: 480px) {
	.financing-hub__path-option {
		padding: var(--wp--preset--spacing--30);
		gap: var(--wp--preset--spacing--10);
	}

	.financing-hub__path-option-icon {
		width: 34px;
		height: 34px;
	}
}

[data-financing-guided-back-to-chooser],
[data-financing-manual-back-to-chooser] {
	margin-bottom: var(--wp--preset--spacing--30);
}

.financing-hub__guided-step-title {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--md, 1.05rem);
}

.financing-hub__guided-options {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
	gap: var(--wp--preset--spacing--20);
	margin-bottom: var(--wp--preset--spacing--30);
}

.financing-hub__guided-option {
	min-height: 44px;
	padding: var(--wp--preset--spacing--30);
	background: var(--wp--preset--color--paper);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 18%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	cursor: pointer;
	font: inherit;
	font-weight: 600;
	text-align: left;
}

.financing-hub__guided-option:hover,
.financing-hub__guided-option:focus-visible {
	border-color: var(--wp--preset--color--brand-gold-700);
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 8%, transparent);
}

.financing-hub__guided-skip {
	margin-bottom: var(--wp--preset--spacing--30);
}

.financing-hub__guided-result-card {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
	padding: var(--wp--preset--spacing--40);
	margin-bottom: var(--wp--preset--spacing--40);
	background: color-mix(in srgb, var(--wp--preset--color--ink) 4%, var(--wp--preset--color--paper));
	border-radius: var(--wp--custom--radius--sm);
}

.financing-hub__guided-result-card img {
	max-width: 160px;
	height: auto;
}

.financing-hub__guided-result-name {
	font-weight: 700;
	margin: 0;
}

.financing-hub__guided-result-price {
	font-weight: 700;
	font-size: var(--wp--preset--font-size--lg);
	color: var(--wp--preset--color--brand-gold-700);
	margin: 0;
}

.financing-hub__guided-result-reasons {
	margin: 0;
	padding-left: 1.2em;
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 70%, transparent);
}

.financing-hub__guided-result-actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20);
}

/* CP-023 Fase 1: this block IS the "resumo compacto + Alterar" the
   progressive-disclosure redesign needs for step 1 — a real visual
   redesign here (compact bar, brand-gold left accent reading as
   "resolved"), not new markup: .financing-hub__product-selected already
   held name+variation+"Alterar equipamento" before this pass. */
.financing-hub__product-selected {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--30);
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 6%, var(--wp--preset--color--paper));
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
	border-left: 3px solid var(--wp--preset--color--brand-gold-700);
	border-radius: var(--wp--custom--radius--sm);
}

.financing-hub__product-selected-summary {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--10);
}

.financing-hub__product-selected [data-financing-change-product] {
	flex: 0 0 auto;
	margin-left: auto;
}

/* Same class of bug as .wc-block-cart-item__image img[hidden] elsewhere in
   this file: author-origin `display: flex/inline-flex` beats the UA
   stylesheet's `[hidden] { display: none }` regardless of specificity, so
   the server-rendered `hidden` attribute (and financing-hub.js's `hidden =
   true/false` toggling) had no visible effect on these two without this. */
.financing-hub__product-selected[hidden],
.financing-hub__empty[hidden],
.financing-hub__unavailable[hidden] {
	display: none;
}

.financing-hub__product-name {
	margin: 0;
	font-weight: 700;
}

.financing-hub__product-variation {
	margin: 0;
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 70%, var(--wp--preset--color--paper));
}

.financing-hub__product-picker label,
.financing-hub__step label {
	display: block;
	margin-bottom: var(--wp--preset--spacing--20);
	font-weight: 600;
}

/* Gate 3: a label must never sit above a hidden control (Frequência/
   Número de prestações have no visible select while no financing profile
   is resolved yet) — the generic rule above sets display:block on every
   label, so [hidden] alone would otherwise be silently overridden. */
.financing-hub__step label[hidden] {
	display: none;
}

/* Gate 2 — accessible combobox wrapper: input + heading + listbox + status
   all sit in normal document flow (never a floating/absolutely-positioned
   overlay), so the results list can never be clipped by a viewport edge or
   covered by the mobile virtual keyboard — the concern the task's own
   "nenhum dropdown cortado" requirement is really about. */
.financing-hub__combobox {
	position: relative;
}

.financing-hub__results-heading {
	margin: var(--wp--preset--spacing--30) 0 var(--wp--preset--spacing--10);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 60%, transparent);
}

.financing-hub__results-heading[hidden] {
	display: none;
}

.financing-hub__search-status {
	margin: var(--wp--preset--spacing--20) 0 0;
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, transparent);
	min-height: 1.2em;
}

/* Gate 2 fail-safe UX: entrada/periodicidade/prestações/resultado while no
   product is selected. A background tint (not opacity) keeps every label/
   value at full contrast — opacity alone was explicitly rejected by this
   task's own acceptance criteria ("não dependa apenas de redução de
   opacidade") since it dims text below AA on an already-light background. */
.financing-hub__locked-notice {
	margin: 0 0 var(--wp--preset--spacing--30);
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	background: color-mix(in srgb, var(--wp--preset--color--ink) 6%, var(--wp--preset--color--paper));
	border-left: 3px solid color-mix(in srgb, var(--wp--preset--color--ink) 25%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
}

.financing-hub__locked-notice[hidden] {
	display: none;
}

.financing-hub__step[aria-disabled="true"] .financing-hub__entry-numeric input,
.financing-hub__step[aria-disabled="true"] select {
	cursor: not-allowed;
	background: color-mix(in srgb, var(--wp--preset--color--ink) 4%, var(--wp--preset--color--paper));
	/* Browser default disabled text (often a low-contrast GrayText) would
	   fail the "preserve contraste e legibilidade" requirement — kept at
	   the same ink color as an enabled field, the tint + not-allowed
	   cursor + locked-notice text above already communicate "unavailable"
	   without sacrificing readability. */
	color: var(--wp--preset--color--ink);
	-webkit-text-fill-color: var(--wp--preset--color--ink);
	opacity: 1;
}

.financing-hub__step[aria-disabled="true"] button[disabled] {
	cursor: not-allowed;
}

.financing-hub__results {
	list-style: none;
	margin: var(--wp--preset--spacing--30) 0 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
	max-height: 320px;
	overflow-y: auto;
}

.financing-hub__result-item {
	width: 100%;
	text-align: left;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--paper);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 15%, transparent);
	border-radius: var(--wp--custom--radius--sm);
	cursor: pointer;
	font: inherit;
}

.financing-hub__result-item:hover,
.financing-hub__result-item[aria-selected="true"] {
	border-color: var(--wp--preset--color--brand-gold-700);
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 8%, transparent);
}

.financing-hub__result-item:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 2px;
}

.financing-hub__variation-picker {
	margin-top: var(--wp--preset--spacing--40);
}

/* Gate 3: entry slider + numeric field, kept in sync (financing-hub.js).
   The numeric field stays the form-of-record for typing/screen readers;
   the slider is a large, thumb-friendly alternative — neither depends on
   the other to be usable. */
.financing-hub__entry-control {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--30);
}

.financing-hub__entry-slider {
	width: 100%;
	appearance: none;
	-webkit-appearance: none;
	height: var(--wp--preset--spacing--20);
	border-radius: var(--wp--custom--radius--pill);
	background: color-mix(in srgb, var(--wp--preset--color--ink) 12%, var(--wp--preset--color--paper));
	outline-offset: 4px;
}

.financing-hub__entry-slider:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

.financing-hub__entry-slider:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
}

.financing-hub__entry-slider::-webkit-slider-thumb {
	appearance: none;
	-webkit-appearance: none;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	background: var(--wp--preset--color--brand-gold-700);
	border: 3px solid var(--wp--preset--color--paper);
	box-shadow: 0 1px 3px color-mix(in srgb, var(--wp--preset--color--ink) 30%, transparent);
	cursor: pointer;
}

.financing-hub__entry-slider:disabled::-webkit-slider-thumb {
	cursor: not-allowed;
}

.financing-hub__entry-slider::-moz-range-thumb {
	width: 28px;
	height: 28px;
	border-radius: 50%;
	background: var(--wp--preset--color--brand-gold-700);
	border: 3px solid var(--wp--preset--color--paper);
	box-shadow: 0 1px 3px color-mix(in srgb, var(--wp--preset--color--ink) 30%, transparent);
	cursor: pointer;
}

.financing-hub__entry-slider::-moz-range-track {
	height: var(--wp--preset--spacing--20);
	border-radius: var(--wp--custom--radius--pill);
	background: transparent;
}

.financing-hub__entry-numeric {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--10);
	max-width: 220px;
}

.financing-hub__entry-numeric label {
	margin-bottom: 0;
	font-weight: 600;
}

.financing-hub__entry-bounds {
	margin: var(--wp--preset--spacing--20) 0 0;
	font-size: var(--wp--preset--font-size--sm, 0.9rem);
	/* CP-023 Fase 1: pre-existing 70% mix measured at 4.41:1 (axe, AA
	   requires 4.5:1) — this line is now more prominently visible right
	   under the collapsed step-1 summary, so fixed in the same pass;
	   76% clears AA. Value-only change, no structural/behavioral edit. */
	color: color-mix(in srgb, var(--wp--preset--color--ink) 76%, transparent);
}

.financing-hub__result {
	margin-top: var(--wp--preset--spacing--40);
	padding: var(--wp--preset--spacing--40);
	background: color-mix(in srgb, var(--wp--preset--color--ink) 4%, var(--wp--preset--color--paper));
	border-radius: var(--wp--custom--radius--sm);
}

.financing-hub__result-list {
	display: grid;
	gap: var(--wp--preset--spacing--30);
	margin: var(--wp--preset--spacing--30) 0;
}

/* Found while verifying the financing-modal auto-advance fix: this class's
   own `display: grid` ties the browser's native `[hidden] { display: none }`
   on specificity, and — because it's an author rule — wins by cascade order.
   The dt/dd labels rendered with no values ("Deposit / Estimated instalment
   / …") even though `data-fpm-result` carried `hidden` and no simulation had
   run. Restoring the actual hide. */
.financing-hub__result-list[hidden] {
	display: none;
}

.financing-hub__result-list > div {
	display: flex;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--30);
}

.financing-hub__result-list dt {
	font-weight: 600;
}

.financing-hub__result-list dd {
	margin: 0;
	font-weight: 700;
}

.financing-hub__disclaimer {
	margin: 0;
	font-size: var(--wp--preset--font-size--sm);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
}

.financing-hub__field {
	margin-bottom: var(--wp--preset--spacing--40);
}

/* --- International phone field (vendored intl-tel-input, moved here from
   the retired CP-009A dialog CSS — this is now the only surface using it).
   The library only ever sets positioning on .iti__tel-input (no border/
   padding/background), so the input keeps the normal .form-input look;
   these rules only make the wrapper full-width and theme the
   country-selector button to the existing tokens instead of the library's
   default gray palette. --- */

.financing-hub__field .iti {
	display: block;
	width: 100%;
	--iti-border-color: color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	--iti-hover-color: color-mix(in srgb, var(--wp--preset--color--brand-gold) 25%, transparent);
	--iti-country-selector-bg: var(--wp--preset--color--paper);
	--iti-icon-color: var(--wp--preset--color--ink);
}

.financing-hub__field .iti__selected-country {
	min-width: 44px;
}

.financing-hub__field .iti__selected-country:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: -2px;
}

.financing-hub__field .iti__country-list {
	font-size: var(--wp--preset--font-size--sm);
	border-radius: var(--wp--custom--radius--sm);
	border-color: color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
}

.financing-hub [aria-busy="true"] {
	opacity: 0.7;
	cursor: wait;
}

.financing-hub__error {
	margin: var(--wp--preset--spacing--20) 0 0;
	color: var(--wp--preset--color--error);
	font-size: var(--wp--preset--font-size--sm);
}

.financing-hub [aria-invalid="true"] {
	border-color: var(--wp--preset--color--error);
}

.financing-hub__honeypot {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
}

.financing-hub__status {
	margin-bottom: var(--wp--preset--spacing--40);
}

.financing-hub__whatsapp {
	margin-top: var(--wp--preset--spacing--40);
}

.financing-hub__noscript {
	margin-bottom: var(--wp--preset--spacing--50);
}

/* =========================================================
   Gate 6 — Contactos detailed contact form. Same field/error/status/
   honeypot chrome as .financing-hub (see above), scoped under its own
   class so neither surface can accidentally leak the other's styling.
   ========================================================= */

.contact-form {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--10);
	margin-block: var(--wp--preset--spacing--50);
}

.contact-form__field {
	margin-bottom: var(--wp--preset--spacing--40);
}

.contact-form__field label {
	display: block;
	margin-bottom: var(--wp--preset--spacing--20);
	font-weight: 600;
}

.contact-form__checkbox-label {
	display: flex;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--20);
	font-weight: 400;
}

.contact-form__checkbox-label input[type="checkbox"] {
	margin-top: 0.2em;
	width: 20px;
	height: 20px;
	flex-shrink: 0;
}

.contact-form__error {
	margin: var(--wp--preset--spacing--20) 0 0;
	color: var(--wp--preset--color--error);
	font-size: var(--wp--preset--font-size--sm);
}

.contact-form [aria-invalid="true"] {
	border-color: var(--wp--preset--color--error);
}

.contact-form__honeypot {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
}

.contact-form__status {
	margin-bottom: var(--wp--preset--spacing--40);
}

.contact-form [aria-busy="true"] {
	opacity: 0.7;
	cursor: wait;
}

.contact-form__noscript {
	margin-bottom: var(--wp--preset--spacing--50);
}

/* =========================================================
   Quick-add dialog (CP-018) — variable-product quick variation
   select, triggered from a product card. Native <dialog>: free
   focus-trap/Escape/focus-return, no library.
   ========================================================= */

.quick-add-dialog {
	position: fixed;
	box-sizing: border-box;
	border: none;
	border-radius: var(--wp--custom--radius--lg);
	padding: var(--wp--preset--spacing--50);
	width: min(420px, calc(100vw - 48px));
	box-shadow: 0 20px 48px rgba(0, 0, 0, 0.28);
}

.quick-add-dialog::backdrop {
	background: color-mix(in srgb, var(--wp--preset--color--ink) 55%, transparent);
}

.quick-add-dialog__form {
	position: relative;
}

.quick-add-dialog__close {
	position: absolute;
	top: 0;
	right: 0;
}

.quick-add-dialog__title {
	margin: 0 var(--wp--preset--spacing--60) var(--wp--preset--spacing--20) 0;
	font-size: var(--wp--preset--font-size--lg);
}

.quick-add-dialog__price {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-weight: 700;
}

.quick-add-dialog__label {
	display: block;
	margin-bottom: var(--wp--preset--spacing--10, 4px);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--sm);
}

.quick-add-dialog__select {
	width: 100%;
	margin-bottom: var(--wp--preset--spacing--30);
}

.quick-add-dialog__error {
	margin: 0 0 var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--error);
	font-size: var(--wp--preset--font-size--sm);
}

.quick-add-dialog__submit {
	width: 100%;
}

.quick-add-dialog__success {
	margin: 0;
	text-align: center;
	color: var(--wp--preset--color--success);
	font-weight: 700;
}

.stock-alert-dialog__note {
	margin: 0 0 var(--wp--preset--spacing--30);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, var(--wp--preset--color--paper));
	font-size: var(--wp--preset--font-size--sm);
}

.stock-alert-dialog__email {
	width: 100%;
	margin-bottom: var(--wp--preset--spacing--30);
}

@media (max-width: 781px) {
	/* Bottom-sheet: the UA stylesheet centers <dialog> via `margin: auto`
	   on every side when shown with showModal() — overriding just the
	   block-start margin anchors it to the bottom instead, keeping the
	   existing horizontal centering/full-width behavior. */
	.quick-add-dialog {
		margin-block-start: auto;
		margin-block-end: 0;
		width: 100%;
		max-width: none;
		border-radius: var(--wp--custom--radius--lg) var(--wp--custom--radius--lg) 0 0;
		padding-bottom: var(--wp--preset--spacing--70);
	}
}

/* =========================================================
   Gate 7 — Sobre a Credphone (page-sobre.html). Reuses existing
   .section/.section-heading/.benefits-grid/.benefit-item/.support-cta
   patterns already established on Home — no new visual language, per
   the design freeze ("later tasks consume existing components/tokens").
   ========================================================= */

.about-hero {
	padding-block: var(--wp--preset--spacing--70);
	padding-inline: var(--wp--preset--spacing--60);
	background: linear-gradient(165deg, color-mix(in srgb, var(--wp--preset--color--brand-gold) 14%, var(--wp--preset--color--paper)), var(--wp--preset--color--paper) 65%);
	border-radius: var(--wp--custom--radius--lg);
	box-sizing: border-box;
}

@media (max-width: 781px) {
	.about-hero {
		padding-inline: var(--wp--preset--spacing--40);
	}
}

/* WP's constrained-layout CSS auto-centers any direct section child
   narrower than the 1280px content size (`margin-inline: auto
   !important`) — these must instead share the heading's left edge, same
   fix already applied to .section-heading above. */
.about-hero__title,
.about-hero__lead,
.about-mission__text,
.about-trust__text {
	margin-inline: 0 !important;
}

.about-hero__title {
	max-width: 46rem;
	font-size: var(--wp--preset--font-size--2xl);
	line-height: 1.15;
	margin-block: 0 var(--wp--preset--spacing--30);
}

.about-hero__lead {
	max-width: 42rem;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 75%, transparent);
	margin-block: 0 var(--wp--preset--spacing--50);
}

.about-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--30);
}

.about-mission__text,
.about-trust__text {
	max-width: 52rem;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 80%, transparent);
}

.about-trust__text + .about-trust__text {
	margin-top: var(--wp--preset--spacing--30);
}

.about-stats__grid {
	text-align: center;
}

.about-stats__number {
	margin: 0 0 var(--wp--preset--spacing--10);
	font-size: var(--wp--preset--font-size--2xl);
	font-weight: 700;
	color: var(--wp--preset--color--brand-gold-700);
}

.about-how__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--wp--preset--spacing--50);
}

.about-how__step {
	display: flex;
	gap: var(--wp--preset--spacing--30);
}

.about-how__step-number {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	border-radius: 50%;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--brand-gold);
	font-weight: 700;
}

.about-how__step-title {
	margin: 0 0 var(--wp--preset--spacing--10);
	font-size: var(--wp--preset--font-size--base);
}

.about-how__step-text {
	margin: 0;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 75%, transparent);
	font-size: var(--wp--preset--font-size--sm);
}

@media (max-width: 781px) {
	.about-how__list {
		grid-template-columns: 1fr;
	}

	.about-hero__title {
		font-size: var(--wp--preset--font-size--xl);
	}
}

/* =========================================================
   CP-035 — first-party cookie consent presentation.
   The state model and optional-resource gate live in credphone-core.
   ========================================================= */

.cookie-consent[hidden],
.cookie-preferences:not([open]) {
	display: none;
}

.cookie-consent {
	position: fixed;
	z-index: 100000;
	right: clamp(16px, 3vw, 40px);
	bottom: clamp(16px, 3vw, 40px);
	left: clamp(16px, 3vw, 40px);
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: center;
	gap: var(--wp--preset--spacing--50);
	max-width: 1180px;
	max-height: calc(100dvh - 32px);
	margin-inline: auto;
	padding: var(--wp--preset--spacing--50);
	box-sizing: border-box;
	overflow: auto;
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 18%, transparent);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: 0 18px 50px color-mix(in srgb, var(--wp--preset--color--ink) 22%, transparent);
}

.cookie-consent__title,
.cookie-preferences__title,
.cookie-category__title {
	margin: 0;
}

.cookie-consent__title {
	font-size: var(--wp--preset--font-size--lg);
}

.cookie-consent__text,
.cookie-preferences__intro,
.cookie-category__description {
	margin: var(--wp--preset--spacing--20) 0 0;
	color: color-mix(in srgb, var(--wp--preset--color--ink) 78%, transparent);
}

.cookie-consent__actions,
.cookie-preferences__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
}

.cookie-consent__actions .btn:not(.btn--text) {
	min-width: 168px;
}

.cookie-consent__manage {
	min-height: 44px;
	font-weight: 600;
}

.cookie-preferences {
	width: min(680px, calc(100% - 32px));
	max-height: calc(100dvh - 32px);
	padding: 0;
	color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--paper);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 18%, transparent);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: 0 18px 60px color-mix(in srgb, var(--wp--preset--color--ink) 28%, transparent);
}

.cookie-preferences::backdrop {
	background: color-mix(in srgb, var(--wp--preset--color--ink) 55%, transparent);
}

.cookie-preferences__panel {
	box-sizing: border-box;
	max-height: calc(100dvh - 34px);
	padding: var(--wp--preset--spacing--50);
	overflow: auto;
}

.cookie-preferences__header {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--30);
}

.cookie-preferences__close {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	flex: 0 0 auto;
	font: inherit;
	font-size: 1.75rem;
	line-height: 1;
	background: transparent;
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 30%, transparent);
	border-radius: var(--wp--custom--radius--md);
	cursor: pointer;
}

.cookie-preferences__categories {
	display: grid;
	gap: var(--wp--preset--spacing--30);
	margin-block: var(--wp--preset--spacing--50);
}

.cookie-category {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: center;
	gap: var(--wp--preset--spacing--40);
	padding: var(--wp--preset--spacing--40);
	background: color-mix(in srgb, var(--wp--preset--color--paper) 92%, var(--wp--preset--color--ink));
	border-radius: var(--wp--custom--radius--md);
}

.cookie-category__title {
	font-size: var(--wp--preset--font-size--base);
}

.cookie-category__description {
	font-size: var(--wp--preset--font-size--sm);
}

.cookie-category__control {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
}

.cookie-category__control input {
	width: 24px;
	height: 24px;
	accent-color: var(--wp--preset--color--brand-gold-700);
}

.cookie-settings-control {
	position: fixed;
	z-index: 29;
	left: var(--wp--preset--spacing--30);
	bottom: calc(var(--wp--preset--spacing--30) + env(safe-area-inset-bottom, 0px));
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 18%, transparent);
	border-radius: var(--wp--custom--radius--md);
	box-shadow: 0 2px 8px color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
	cursor: pointer;
}

.cookie-settings-control__icon {
	display: block;
	width: 20px;
	height: 20px;
	object-fit: contain;
}

.cookie-settings-control[hidden] {
	display: none;
}

.cookie-settings-control:hover {
	background: color-mix(in srgb, var(--wp--preset--color--brand-gold) 10%, var(--wp--preset--color--paper));
	border-color: color-mix(in srgb, var(--wp--preset--color--brand-gold) 45%, transparent);
}

.cookie-settings-control:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand-gold-700);
	outline-offset: 2px;
}

/* The fixed control visually belongs outside the footer, but when the page
   reaches its bottom its screen position overlaps the footer's left edge.
   Reserve only that small bottom-row area while the control is active; the
   Legal list itself remains cookie-control-free. */
.has-cookie-settings-control .site-footer__bottom,
.has-cookie-settings-control .site-footer--checkout .site-footer__checkout-row {
	box-sizing: border-box;
	padding-left: 68px;
}

@media (max-width: 430px) {
	.has-cookie-settings-control .site-footer__bottom,
	.has-cookie-settings-control .site-footer--checkout .site-footer__checkout-row {
		min-height: 52px;
		padding-left: 60px;
	}
}

@media (max-width: 1023px) {
	.cookie-consent {
		grid-template-columns: 1fr;
	}
}

@media (max-width: 600px) {
	.cookie-consent,
	.cookie-preferences__panel {
		padding: var(--wp--preset--spacing--40);
	}

	.cookie-consent__actions,
	.cookie-preferences__actions {
		display: grid;
		grid-template-columns: 1fr;
	}

	.cookie-consent__actions .btn,
	.cookie-preferences__actions .btn {
		width: 100%;
	}

	.cookie-category {
		grid-template-columns: 1fr;
	}

	.cookie-category__control {
		justify-self: start;
	}
}

/* CP-039 — CTA "Saldos 🔥" na navegação principal, logo a seguir a "Loja".
   Polish 2026-10-13: o PO não aprovou a pill dourada original — o link
   agora integra-se naturalmente como qualquer outro item da nav (herda
   `.site-nav .wp-block-navigation-item__content`, ~linha 762: sublinhado
   dourado animado no hover/focus), só o emoji "🔥" o distingue
   visualmente. Abre o popup via saldos-modal.js (href é só fallback
   semântico, nunca é seguido com JS ativo). Visibilidade condicional
   (0 produtos elegíveis = link nem chega a ser impresso) é tratada
   server-side em includes/catalog/saldos.php — zero CSS necessário aqui
   para o estado vazio. */

/* Popup "Saldos" — mesmo padrão <dialog> nativo do quick-add-dialog
   (focus trap/Escape/devolução de foco geridos pelo navegador), só mais
   largo por ser uma grelha de produtos em vez de um formulário. */
.saldos-modal {
	position: fixed;
	box-sizing: border-box;
	border: none;
	border-radius: var(--wp--custom--radius--lg);
	padding: var(--wp--preset--spacing--50);
	width: min(960px, calc(100vw - 48px));
	max-height: min(760px, calc(100vh - 64px));
	box-shadow: 0 20px 48px rgba(0, 0, 0, 0.28);
}

.saldos-modal::backdrop {
	background: color-mix(in srgb, var(--wp--preset--color--ink) 55%, transparent);
}

.saldos-modal__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: var(--wp--preset--spacing--40);
}

.saldos-modal__header h2 {
	margin: 0;
	font-size: var(--wp--preset--font-size--lg);
}

.saldos-modal__close {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	border: none;
	border-radius: 50%;
	background: transparent;
	color: currentColor;
	cursor: pointer;
}

.saldos-modal__close:hover,
.saldos-modal__close:focus-visible {
	background: color-mix(in srgb, currentColor 10%, transparent);
}

.saldos-modal__body {
	overflow-y: auto;
	max-height: calc(min(760px, 100vh - 64px) - 96px);
}

.saldos-modal__loading,
.saldos-modal__empty,
.saldos-modal__error {
	margin: var(--wp--preset--spacing--60) 0;
	text-align: center;
	color: var(--wp--preset--color--ink-60, #666);
}

.saldos-modal__grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
	gap: var(--wp--preset--spacing--40);
}

.saldos-modal__card {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--10, 4px);
	color: inherit;
	text-decoration: none;
}

.saldos-modal__media {
	position: relative;
	aspect-ratio: 1;
	border-radius: var(--wp--custom--radius--md);
	background: var(--wp--preset--color--paper-dim, #f5f5f5);
	overflow: hidden;
}

.saldos-modal__media img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.saldos-modal__badge {
	position: absolute;
	top: 8px;
	left: 8px;
	padding: 2px 8px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--brand-gold);
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--xs, 12px);
	font-weight: 700;
}

.saldos-modal__name {
	margin: 0;
	font-weight: 600;
	font-size: var(--wp--preset--font-size--sm);
}

.saldos-modal__price {
	font-weight: 700;
}

.saldos-modal__price del {
	margin-right: 6px;
	font-weight: 400;
	opacity: 0.6;
}

.saldos-modal__cta {
	font-size: var(--wp--preset--font-size--sm);
	text-decoration: underline;
}

@media (max-width: 480px) {
	.saldos-modal {
		width: calc(100vw - 32px);
		padding: var(--wp--preset--spacing--40);
	}

	.saldos-modal__grid {
		grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
	}
}

/* CP-039 pre-live polish (P1) — checkout-payment-loading.js toggles this
   class on <html> only while #payment-method contains nothing but Woo
   Blocks' own "no payment methods yet" notice (confirmed live: genuinely
   true for ~2-4s while Stripe's iframe-based Payment Element/Apple Pay/
   Google Pay/Link are still registering). Pure CSS: the real notice keeps
   its layout box (visibility, not display, so nothing shifts when it's
   removed) while a neutral loading line covers it via `content` — no DOM
   edit inside the React-owned checkout subtree. Removed automatically the
   instant a real payment method registers, or by the script's own safety
   ceiling if one never does. */
html.credphone-payment-loading #payment-method .wc-block-checkout__no-payment-methods-notice {
	visibility: hidden;
}

html.credphone-payment-loading #payment-method .wc-block-components-notices {
	position: relative;
	min-height: 2.75em;
}

html.credphone-payment-loading #payment-method .wc-block-components-notices::after {
	content: "A carregar métodos de pagamento…";
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--sm);
}

/* =========================================================
   iPhone 18 landing page (/iphone-18/) — Apple 2026 New Lineup
   Reuses .section/.section-heading/.benefits-grid/.benefit-item/.btn
   unchanged; only the hero, compare cards and color grid below are new,
   scoped-prefixed to avoid colliding with any other page.
   ========================================================= */

.iphone18-hero {
	width: 100vw;
	margin-inline: calc(50% - 50vw);
	background: linear-gradient(135deg, #0d0d0d 0%, var(--wp--preset--color--ink) 55%, #241a10 100%);
	color: var(--wp--custom--text--on-inverse);
}

.iphone18-hero__inner {
	display: grid;
	grid-template-areas: "copy media";
	grid-template-columns: 1.1fr 0.9fr;
	align-items: center;
	gap: var(--wp--preset--spacing--60);
	max-width: 1280px;
	margin-inline: auto;
	padding-inline: max(var(--wp--preset--spacing--30), calc((100% - 1280px) / 2));
	padding-block: var(--wp--preset--spacing--80);
}

.iphone18-hero__copy {
	grid-area: copy;
}

.iphone18-hero__eyebrow {
	margin: 0 0 var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--wp--preset--color--brand-gold);
}

.iphone18-hero__title {
	margin: 0 0 var(--wp--preset--spacing--40);
	font-size: clamp(2.25rem, 1.5rem + 3vw, 3.75rem);
	line-height: 1.05;
	letter-spacing: -0.02em;
	font-weight: 700;
}

.iphone18-hero__lead {
	max-width: 42ch;
	margin: 0 0 var(--wp--preset--spacing--50);
	font-size: var(--wp--preset--font-size--lg);
	color: color-mix(in srgb, var(--wp--custom--text--on-inverse) 85%, transparent);
}

.iphone18-hero__media {
	grid-area: media;
	display: flex;
	justify-content: center;
}

.iphone18-hero__media img {
	width: 100%;
	max-width: 360px;
	height: auto;
}

@media (max-width: 781px) {
	.iphone18-hero__inner {
		grid-template-areas: "media" "copy";
		grid-template-columns: 1fr;
		text-align: center;
		padding-block: var(--wp--preset--spacing--60);
	}

	.iphone18-hero__lead {
		margin-inline: auto;
	}

	.iphone18-hero__media img {
		max-width: 280px;
	}
}

.iphone18-lineup-grid {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--40);
}

.iphone18-lineup-grid li.wc-block-product {
	flex: 1 1 280px;
}

.iphone18-compare-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--wp--preset--spacing--50);
}

.iphone18-compare-card {
	padding: var(--wp--preset--spacing--50);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 12%, transparent);
	border-radius: 4px;
}

.iphone18-compare-card__title {
	margin: 0 0 var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--lg);
}

.iphone18-compare-card__hint {
	margin: 0 0 var(--wp--preset--spacing--30);
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, transparent);
	font-size: var(--wp--preset--font-size--sm);
}

.iphone18-compare-card__list {
	list-style: none;
	margin: 0 0 var(--wp--preset--spacing--40);
	padding: 0;
}

.iphone18-compare-card__list li {
	display: flex;
	justify-content: space-between;
	padding-block: var(--wp--preset--spacing--20);
	border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 10%, transparent);
	font-size: var(--wp--preset--font-size--sm);
}

.iphone18-compare-card__list li span {
	color: color-mix(in srgb, var(--wp--preset--color--ink) 65%, transparent);
}

@media (max-width: 781px) {
	.iphone18-compare-grid {
		grid-template-columns: 1fr;
	}
}

.iphone18-colors-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--wp--preset--spacing--40);
}

.iphone18-color-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	padding: var(--wp--preset--spacing--30);
	background: color-mix(in srgb, var(--wp--preset--color--ink) 4%, var(--wp--preset--color--paper));
	border-radius: 4px;
}

.iphone18-color-card img {
	width: 100%;
	height: auto;
	max-width: 160px;
}

.iphone18-color-card__label {
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
}

@media (max-width: 781px) {
	.iphone18-colors-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}
