/* ==========================================================================
   BOOM — component & layout styles (built on tokens.css)
   Mobile-first app layout.
   ========================================================================== */

/*
 * tokens.css maps --color-bg-page to the cream #F1EFE8 swatch, which the
 * design system labels "page background". Inspecting the actual mockup's
 * computed styles shows the real in-app content background is #F7F6FB (the
 * lavender tint) — #F1EFE8 is the desktop backdrop *around* the app's rounded
 * card frame, not the app content itself. --color-bg-desk carries that
 * backdrop color separately so <body> and the app frame can each have their
 * own background, matching the mockup's boxed card-on-canvas structure.
 */
:root {
	--color-bg-page: var(--lavender-tint);
	--color-bg-desk: var(--cream-100);
}

/* ---------- Base reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
/* Block pinch-zoom and double-tap-zoom (2026-07-19, explicit user request —
   header.php's <meta viewport maximum-scale=1,user-scalable=no> alone
   doesn't stop it: iOS Safari has ignored user-scalable=no for pinch since
   iOS 10, only actually honoring maximum-scale as a cap — see explanation.md
   §41's own note about this same override for the input-focus auto-zoom
   case). touch-action:pan-x pan-y keeps normal scrolling/dragging working
   (popups, "monte seu pedido" combobox panels, etc.) while disabling the
   browser's own pinch/double-tap zoom gestures — boom.js's gesturestart
   prevention below is the defense-in-depth fallback for older WebKit that
   doesn't honor touch-action for this. */
html, body { touch-action: pan-x pan-y; }
body {
	margin: 0;
	background: var(--color-bg-desk);
	color: var(--color-text-primary);
	font-family: var(--font-body);
	font-size: var(--text-base);
	/* Twenty Twenty-Five (parent theme) sets body font-weight:300 in its own
	   global styles; anything here that only sets font-size (not the full
	   `font:` shorthand) was silently inheriting that instead of a normal 400,
	   reading noticeably thinner/lighter than the mockup. */
	font-weight: var(--weight-regular);
	line-height: var(--leading-normal);
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}
img, svg { max-width: 100%; height: auto; display: block; }
a { color: var(--color-link); text-decoration: none; -webkit-tap-highlight-color: transparent; }
a:hover { color: var(--color-link-hover); text-decoration: underline; }
a:active { color: var(--color-link-hover); }

/* On-dark link context: any link inside a [data-on-dark] container (or
   itself carrying the attribute) hovers/activates toward white instead of
   the light-surface default's darken-toward-violet-700, which silently
   killed contrast on the My Account header card and the footer-trust card.
   Icons/text inside these links already inherit color from the <a> (font
   icons use the color property directly), so no separate currentColor rule
   is needed. :active is declared explicitly since touch devices have no
   :hover — feedback there comes from :active alone. */
[data-on-dark] a,
a[data-on-dark] {
	color: var(--color-link-on-dark);
}
[data-on-dark] a:hover,
a[data-on-dark]:hover {
	color: var(--color-link-on-dark-hover);
	text-decoration: underline;
}
[data-on-dark] a:active,
a[data-on-dark]:active {
	color: var(--color-link-on-dark-hover);
}
[data-on-dark] a:focus-visible,
a[data-on-dark]:focus-visible {
	outline: 2px solid var(--color-link-on-dark-hover);
	outline-offset: 2px;
}
button { font-family: inherit; cursor: pointer; }
:focus-visible { outline: 2px solid var(--color-border-brand); outline-offset: 2px; border-radius: 4px; }

/* ---------- App frame ----------
   .boom-header and .boom-app each center to the same max-width and paint
   their own background, forming one continuous "card" (white header top +
   lavender body bottom) that floats on the cream --color-bg-desk backdrop —
   no extra wrapper div needed. Below 480px the card fills the real viewport
   (there's no backdrop showing anyway), so the radius/shadow are dropped to
   avoid rounded corners floating with no visible context.
   No bottom padding reserve here for the fixed .boom-bottomnav — that used
   to carry a 96px + safe-area buffer, replaced by margin-bottom below. The
   nav's real on-screen footprint is 45px tall + a 12px offset from the
   viewport bottom (measured in the browser, matches .boom-bottomnav's own
   `bottom: calc(12px + safe-area)`) = 57px it needs clear beneath the card
   at max scroll, or the fixed nav sits directly over .boom-footer's own
   last line (copyright text) instead of empty backdrop — confirmed by
   measuring getBoundingClientRect() at real max scroll, not just eyeballed.
   --space-12 (40px) would already clear that 57px combined with
   .boom-footer's own existing 20px (var(--space-9)) bottom padding, both
   far less than the old fixed 96px reserve — margin-bottom below uses the
   project's own --space-13 (48px, added to tokens.css for this) instead,
   for extra breathing room past that measured minimum. */
.boom-app {
	max-width: 448px;
	margin: 0 auto var(--space-13);
	padding: var(--space-8) var(--page-margin) 0;
	background: var(--color-bg-page);
	position: relative;
}
.boom-section { margin-top: var(--space-10); }
.boom-section:first-child { margin-top: 0; }

/* ---------- Typography helpers ---------- */
.boom-eyebrow {
	font: var(--font-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	color: var(--color-text-brand);
	margin: 0;
}
.boom-eyebrow--caps { text-transform: uppercase; }
.boom-section-head {
	margin-bottom: var(--space-6);
	display: flex;
	align-items: center;
	justify-content: space-between;
}
/* Only used by the "compre com tranquilidade"/"quem confia na boom" header
   rows — matches the mockup's icon-badge + eyebrow-style label exactly
   (uppercase, black weight, 11.5px, violet-700), not the Sora headline
   style .boom-eyebrow's own siblings use elsewhere. */
.boom-section-title {
	font: var(--font-eyebrow);
	text-transform: uppercase;
	letter-spacing: var(--tracking-eyebrow);
	color: var(--color-text-brand-deep);
	margin: 0;
	display: flex;
	align-items: center;
	gap: var(--space-4);
}
.boom-section-sub {
	font: var(--font-caption);
	color: var(--color-text-secondary);
	margin: var(--space-2) 0 0;
}
/* Plain section label (e.g. "escolha sua rede") — quiet and muted.
   Not the same as .boom-eyebrow, which is reserved for the bold kicker
   directly above a headline (e.g. above the hero title). */
.boom-label {
	font: var(--weight-medium) var(--text-sm) var(--font-body);
	color: var(--color-text-secondary);
	margin: 0;
}

/* ---------- Cards ---------- */
.boom-card {
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	border-radius: var(--radius-lg);
	padding: var(--card-padding);
}
.boom-card--tint { background: var(--color-bg-surface-tint); }
.boom-card--dark {
	background: var(--color-bg-hero);
	color: var(--color-text-on-dark);
	border: none;
}

/* ---------- Buttons ---------- */
.boom-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-3);
	font: var(--font-button);
	border: none;
	border-radius: var(--radius-pill);
	padding: var(--space-5) var(--space-9);
	transition: transform var(--duration-fast) var(--ease-standard), filter var(--duration-fast) var(--ease-standard);
	text-align: center;
}
.boom-btn:active { transform: scale(0.97); }
.boom-btn--primary {
	background: var(--color-bg-cta);
	color: #fff;
	box-shadow: var(--shadow-button);
}
.boom-btn--primary:hover { filter: brightness(1.05); color: #fff; }
.boom-btn--ghost {
	background: var(--color-bg-surface-violet-50);
	color: var(--color-text-brand);
}
.boom-btn--block { display: flex; width: 100%; }

/* ==========================================================================
   Header
   ========================================================================== */
.boom-header {
	max-width: 448px;
	margin: 0 auto;
	position: sticky;
	top: 0;
	z-index: 50;
	background: var(--color-bg-surface);
	border-bottom: var(--border-hairline);
}
.boom-header__inner {
	padding: var(--space-7) var(--page-margin);
	display: flex;
	align-items: center;
	gap: var(--space-6);
}
/* itens/dados/pagamento progress card (Carrinho e checkout.dc.html's
   #steps-card) — sits below the hero in page-finalizar-compra.php, split
   into 2 sections (2026-07-26 per user request) so ONLY the step row
   sticks under .boom-header once scroll reaches it — the bell notice above
   it scrolls away normally. Square-corner pairing (notice card rounded top/
   square bottom, steps card square top/rounded bottom) + zero gap between
   them (steps card isn't .boom-section, no auto top margin) makes the two
   read as one continuous card until the notice scrolls out from under the
   sticky one. The bell notice reuses .boom-order-progress-card__notice*
   (thankyou.php's tracker card) verbatim; the step row reuses .boom-step,
   sized to match .boom-order-progress__circle (28px) since both are the
   same kind of component. */
.boom-checkout-notice-card {
	border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.boom-checkout-steps-card {
	position: sticky;
	top: var(--boom-header-height, 70.5px); /* live-measured (initStickyHeaderOffset(), boom.js) — a hardcoded value left a real gap on desktop, where .boom-header renders taller than on mobile */
	z-index: 20;
	border-radius: 0 0 var(--radius-lg) var(--radius-lg);
	box-shadow: var(--shadow-sm);
}
.boom-checkout-steps {
	display: flex; align-items: flex-start;
}
.boom-checkout-steps .boom-step { flex: 1; }
.boom-checkout-steps .boom-step__circle { width: 28px; height: 28px; font-size: 13px; }
.boom-checkout-steps .boom-step__label { font-size: 8.5px; }
.boom-checkout-steps .boom-step__line { flex: 1; margin: 13px var(--space-2) 0; }
/* Scroll-driven fill states (initCheckoutStepTracker(), boom.js) — set
   directly by JS rather than inferred from the preceding .boom-step's
   .is-done (unlike the shared .boom-step.is-done + .boom-step__line rule
   below, which initOrderBuilderStepTracker()'s tracker still relies on)
   so the "dados"→"pagamento" line can carry a third, half-filled state
   while .boom-order-summary is passing under the header.
   A ::after overlay growing in width (not a background swap) so the line
   actually "fills" left-to-right as you scroll, instead of the color just
   cross-fading in place — needs position:relative + overflow:hidden on the
   line itself (its own border-radius clips the overlay's square corners
   for free) and a slower, more visible duration than --duration-base
   (200ms reads as a flicker for a fill sweep; --duration-slow is the
   deliberate choice here). */
.boom-checkout-steps .boom-step__line {
	position: relative;
	overflow: hidden;
}
.boom-checkout-steps .boom-step__line::after {
	content: '';
	position: absolute;
	inset: 0;
	width: 0%;
	background: var(--color-text-brand);
	transition: width var(--duration-slow) var(--ease-standard);
}
.boom-checkout-steps .boom-step__line.is-half::after { width: 50%; }
.boom-checkout-steps .boom-step__line.is-filled::after { width: 100%; }
/* The circle shows its step number by default, swapping to a checkmark once
   .is-done — front-page.php's builder tracker doesn't do this (number stays
   put, only color changes), but the checkout mockup explicitly draws a
   checkmark for completed steps, so this tracker's circle carries both an
   icon and the digit and toggles which is visible. */
.boom-checkout-steps .boom-step__circle i { display: none; font-size: 14px; }
.boom-checkout-steps .boom-step.is-done .boom-step__circle i { display: inline; }
.boom-checkout-steps .boom-step.is-done .boom-step__circle span { display: none; }
.boom-wordmark {
	font-family: var(--font-display);
	font-weight: var(--weight-bold);
	font-size: var(--text-xl);
	letter-spacing: 0.3px;
	color: var(--color-text-brand);
	margin-right: auto;
	white-space: nowrap;
}
.boom-lang {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	font: var(--font-label);
	color: var(--color-text-secondary);
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	border-radius: var(--radius-pill);
	padding: var(--space-2) var(--space-5);
}
.boom-lang__text { font-size: var(--text-2xs); }
/* Own dedicated custom property (not a shared token like --text-sm) so its
   size can be tweaked live in devtools without touching anything else that
   also reads --text-sm -- current value just matches what this already
   rendered at before it had its own class (font: var(--font-label)'s
   --text-sm, inherited). */
.boom-lang__flag {
	--boom-lang-flag-size: var(--text-xl);
	font-size: var(--boom-lang-flag-size);
}
.boom-iconbtn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px; height: 30px;
	border-radius: var(--radius-pill);
	background: transparent;
	border: none;
	color: var(--color-text-secondary);
	font-size: 23.4px;
}
.boom-iconbtn:hover { background: var(--color-bg-surface-violet-50); color: var(--color-text-brand); }
.boom-iconbtn__dot {
	position: absolute; top: 4px; right: 5px;
	width: 6px; height: 6px; border-radius: 50%;
	background: var(--color-accent-pink);
}

/* ==========================================================================
   Hero
   ========================================================================== */
.boom-hero {
	background: var(--color-bg-hero);
	color: var(--color-text-on-dark);
	border-radius: var(--radius-xl);
	padding: var(--space-9);
	position: relative;
	overflow: hidden;
}
.boom-hero__rocket-bg {
	position: absolute;
	top: -33.8px;
	right: -33.8px;
	font-size: 195px;
	color: rgba(255,255,255,0.055);
	pointer-events: none;
	line-height: 1;
}
.boom-hero__eyebrow {
	font: var(--font-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	color: var(--color-text-on-dark-soft);
	display: flex; align-items: center; gap: var(--space-3);
	margin: 0 0 var(--space-5);
}
.boom-hero__title {
	font-family: var(--font-display);
	font-weight: var(--weight-bold);
	font-size: var(--text-2xl);
	line-height: var(--leading-tight);
	letter-spacing: var(--tracking-headline);
	margin: 0 0 var(--space-4);
}
.boom-hero__sub {
	font: var(--font-body-md);
	font-size: var(--text-md);
	color: var(--color-text-on-dark-soft);
	margin: 0;
}

.boom-hero__benefits {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--space-5);
	margin-top: var(--space-5);
	padding-top: var(--space-4);
}
.boom-hero__benefit {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
}
.boom-hero__benefit-icon {
	color: var(--color-text-on-dark-soft);
	font-size: 20.8px;
	display: block;
}
.boom-hero__benefit-title { font: var(--font-label); font-size: var(--text-2xs); font-weight: var(--weight-bold); color: var(--color-text-on-dark); display: block; }

/* ==========================================================================
   "de cara nova" animated badge — shimmering gradient-text below the hero,
   replaces the old static "· de cara nova" hero-eyebrow suffix.
   ========================================================================== */
.boom-cara-nova {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-1);
	margin: var(--space-6) 0 0;
	background: linear-gradient(90deg, var(--violet-600) 0%, var(--violet-600) 35%, var(--violet-300) 50%, var(--violet-600) 65%, var(--violet-600) 100%);
	background-size: 200% 100%;
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: transparent;
	animation: boom-cara-shimmer 3s linear infinite;
}
.boom-cara-nova i { font-size: 15.6px; flex-shrink: 0; }
.boom-cara-nova span { font-size: 11.7px; font-weight: var(--weight-bold); }
@keyframes boom-cara-shimmer {
	0% { background-position: 200% 0; }
	100% { background-position: -200% 0; }
}

/* ==========================================================================
   Cards grid — one-tap access to mais vendidos, promoções, ganhe brindes,
   cashboom, boom assinatura, stories e avisos, desconto no pix, status de
   serviços. 3-column tile grid, same tinted-icon-square treatment as the
   Claude Design mockup's categoryMenu (Boom Home.dc.html).
   ========================================================================== */
.boom-cards {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--space-5);
}
.boom-card-tile {
	display: flex; align-items: center; gap: var(--space-4);
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	box-shadow: var(--shadow-xs);
	border-radius: var(--radius-md);
	padding: var(--space-5) var(--space-6);
	cursor: pointer;
	font-family: inherit;
	text-align: left;
	position: relative;
}
.boom-card-tile__icon {
	flex: 0 0 auto;
	width: 24px; height: 24px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface-tint);
	display: inline-flex; align-items: center; justify-content: center;
}
.boom-card-tile__icon i { font-size: 15.6px; color: var(--color-text-brand-deep); }
.boom-card-tile__text { min-width: 0; }
.boom-card-tile__label {
	display: block;
	font-size: 10.4px; font-weight: var(--weight-bold);
	color: var(--color-text-brand-deep);
	text-transform: uppercase; letter-spacing: 0.2px;
	line-height: 1.25;
}
.boom-card-tile__sub {
	display: block;
	font-size: 8.5px; font-weight: var(--weight-medium);
	color: var(--color-text-secondary);
	line-height: 1.25; margin-top: 1px;
}
.boom-card-tile__badge {
	position: absolute; top: -6px; right: -4px;
	background: var(--pink-500); color: #fff;
	font-size: 7px; font-weight: var(--weight-black);
	letter-spacing: 0.3px;
	padding: 2px 6px; border-radius: var(--radius-pill);
	white-space: nowrap;
}

/* ==========================================================================
   "mais vendidos" on-page section — real WooCommerce bestsellers, same
   $boom_bestsellers data/prefill behavior as the card-tile's popup.
   ========================================================================== */
.boom-bestseller-section__badge {
	width: 24px; height: 24px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface-tint);
	display: inline-flex; align-items: center; justify-content: center;
	box-shadow: var(--shadow-xs);
}
.boom-bestseller-section__badge i { font-size: 16.9px; color: var(--color-text-brand); }
.boom-section-see-all {
	background: none; border: none; padding: 0;
	font-size: 10.4px; font-weight: var(--weight-bold);
	color: var(--color-text-brand);
	text-decoration: none;
	cursor: pointer;
}
.boom-bestseller-card-row {
	display: flex; gap: 11.7px;
	overflow-x: auto;
	padding: 2px 0 5.2px 2px;
	margin-right: calc(-1 * var(--page-margin));
}
.boom-bestseller-card-row.boom-no-scrollbar { scrollbar-width: none; -ms-overflow-style: none; }
.boom-bestseller-card-row.boom-no-scrollbar::-webkit-scrollbar { display: none; }
.boom-bestseller-card {
	flex-shrink: 0; width: 171.6px;
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	border-radius: var(--radius-lg);
	padding: 15.6px;
	display: flex;
	flex-direction: column;
}
.boom-bestseller-card__icon {
	width: 44.2px; height: 44.2px;
	border-radius: 13px;
	background: var(--color-bg-surface-tint);
	display: flex; align-items: center; justify-content: center;
}
.boom-bestseller-card__icon i { font-size: 20.8px; color: var(--color-text-brand); }
.boom-bestseller-card__name {
	font-size: 13px; font-weight: var(--weight-bold);
	color: var(--color-text-primary);
	line-height: 1.3;
	margin: 11.7px 0 0;
}
.boom-bestseller-card__price {
	font-size: 11.7px; font-weight: var(--weight-bold);
	color: var(--color-text-brand);
	margin: 5.2px 0 0;
}
.boom-bestseller-card__cta {
	display: block; width: 100%;
	text-align: center;
	background: var(--color-bg-cta);
	color: #fff;
	border: none; border-radius: 26px;
	padding: 9.1px;
	font-size: 11.7px; font-weight: var(--weight-bold);
	margin-top: auto;
	cursor: pointer;
}
.boom-bestseller-dots { display: flex; justify-content: center; gap: 7.5px; margin-top: var(--space-4); }
.boom-bestseller-dot {
	width: 5px; height: 5px; border-radius: var(--radius-pill);
	background: var(--violet-200);
	transition: width var(--duration-base) var(--ease-standard), background var(--duration-base) var(--ease-standard);
}
.boom-bestseller-dot.is-active { width: 17.5px; background: var(--color-text-brand); }

/* ==========================================================================
   "promoções da semana" on-page section — real $boom_promo_slots data,
   same content as .boom-all-promos-popup (see .boom-promo-card above),
   new glanceable card treatment for the on-page row.
   ========================================================================== */
.boom-promo-section__badge {
	width: 24px; height: 24px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface-tint);
	display: inline-flex; align-items: center; justify-content: center;
	box-shadow: var(--shadow-xs);
}
.boom-promo-section__badge i { font-size: 16.9px; color: var(--color-text-brand); }
.boom-promo-tile-row {
	display: flex; gap: 11.7px;
	overflow-x: auto;
	padding: 2px 0 5.2px 2px;
	margin-right: calc(-1 * var(--page-margin));
}
.boom-promo-tile-row.boom-no-scrollbar { scrollbar-width: none; -ms-overflow-style: none; }
.boom-promo-tile-row.boom-no-scrollbar::-webkit-scrollbar { display: none; }
.boom-promo-tile {
	flex-shrink: 0; width: 291.2px;
	background: var(--color-bg-cta);
	color: #fff;
	border-radius: var(--radius-lg);
	padding: 18.2px;
}
.boom-promo-tile--alt { background: var(--color-bg-hero); }
.boom-promo-tile__head {
	display: flex; align-items: center; justify-content: space-between;
}
.boom-promo-tile__day {
	display: inline-block;
	background: rgba(255,255,255,0.16);
	border-radius: var(--radius-pill);
	padding: 3.9px 11.7px;
	font-size: 9.75px; font-weight: var(--weight-bold);
	text-transform: uppercase; letter-spacing: 0.3px;
}
.boom-promo-tile__pct {
	font-family: var(--font-display);
	font-size: 19.5px; font-weight: var(--weight-black);
}
.boom-promo-tile__desc {
	font-family: var(--font-display);
	font-size: 19.5px; font-weight: var(--weight-bold);
	margin: 11.7px 0 0;
	line-height: 1.3;
}
.boom-promo-tile__example {
	font-size: 11.7px;
	color: rgba(255,255,255,0.85);
	margin: 5.2px 0 0;
	line-height: 1.4;
}
/* Real <button>, not a <span>, wired to scrollToOrderBuilder() via
   initPromoTileCtaScroll() (boom.js) - text changed from "aproveitar" (with
   an arrow icon) to "comprar" 2026-07-29, matching .boom-bestseller-card__cta's
   copy/shape but deliberately smaller ("little" button per the 2026-07-29
   request) since this card already carries a services checklist below it -
   a full-width CTA here would compete with that content instead of just
   punctuating it. */
.boom-promo-tile__cta {
	display: inline-flex; align-items: center; justify-content: center;
	margin-top: 11.7px;
	background: #fff;
	color: var(--color-text-brand);
	border: none;
	border-radius: var(--radius-pill);
	padding: 6.5px 15.6px;
	font-family: inherit;
	font-size: 9.75px; font-weight: var(--weight-bold);
	cursor: pointer;
}
.boom-promo-tile--alt .boom-promo-tile__cta {
	background: var(--color-text-brand);
	color: #fff;
}

/* ==========================================================================
   Status ticker header — pulsing live-dot + "ver tudo", on-page revival of
   $boom_render_status_boxes() (front-page.php). Same underlying CPT/module
   as the "status de serviços" popup (HomeServiceStatus::get_statuses()),
   just a different data shape per surface — see that method's docblock.
   ========================================================================== */
.boom-status-ticker__live { display: flex; align-items: center; gap: 7.8px; }
.boom-status-ticker__dot {
	width: 9px; height: 9px; border-radius: 50%;
	background: var(--color-text-success);
	box-shadow: 0 0 0 3.9px rgba(22,163,74,0.18);
	flex-shrink: 0;
}
.boom-status-ticker__label {
	font-size: 11.7px; font-weight: var(--weight-black);
	color: var(--color-text-brand-deep);
	text-transform: uppercase; letter-spacing: 0.3px;
}

/* ==========================================================================
   Network picker
   ========================================================================== */
.boom-networks {
	display: flex;
	gap: var(--space-5);
	overflow-x: auto;
	scrollbar-width: none;
	padding-bottom: var(--space-2);
}
.boom-networks::-webkit-scrollbar { display: none; }
.boom-network {
	flex: 0 0 auto;
	width: 64px;
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	border-radius: var(--radius-md);
	padding: var(--space-6) var(--space-2) var(--space-4);
	text-align: center;
	color: var(--color-text-secondary);
}
.boom-network__icon { font-size: 28.6px; display: block; margin-bottom: var(--space-3); }
.boom-network__label { font: var(--font-caption); font-size: var(--text-2xs); }
.boom-network--instagram .boom-network__icon { color: #E1306C; }
.boom-network--tiktok .boom-network__icon { color: #1F1B2E; }
.boom-network--youtube .boom-network__icon { color: #FF0000; }
.boom-network--kwai .boom-network__icon { color: #FF6A00; }
.boom-network--facebook .boom-network__icon { color: #1877F2; }

/* ==========================================================================
   Service list
   ========================================================================== */
/* Matches the mockup's real structure: the card itself has zero padding;
   each row carries its own 11px/13px padding so divider lines run edge-to-edge. */
.boom-services { padding: 0; }
.boom-service {
	display: flex;
	align-items: center;
	gap: var(--space-6);
	padding: 11px 13px;
	border-top: var(--border-hairline);
}
.boom-service:first-child { border-top: none; }
.boom-service__icon {
	flex: 0 0 auto;
	width: 40px; height: 40px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-md);
	background: var(--color-bg-surface-violet-50);
	color: var(--color-text-brand);
	font-size: 23.4px;
}
.boom-service__body { flex: 1 1 auto; min-width: 0; }
.boom-service__name { font: var(--font-label); font-size: var(--text-md); color: var(--color-text-primary); margin: 0; }
.boom-service__price { font: var(--font-caption); color: var(--color-text-brand); margin: var(--space-1) 0 0; font-weight: var(--weight-semibold); }
.boom-service__cta {
	flex: 0 0 auto;
	font: var(--font-button);
	font-size: var(--text-sm);
	background: var(--color-bg-cta);
	color: #fff;
	border-radius: var(--radius-pill);
	padding: var(--space-4) var(--space-8);
	box-shadow: var(--shadow-button);
}
.boom-service__cta:hover { color: #fff; filter: brightness(1.05); }

/* ==========================================================================
   Floating bottom nav
   ========================================================================== */
.boom-bottomnav {
	position: fixed;
	left: 50%;
	transform: translateX(-50%) scale(1);
	transform-origin: center bottom;
	transition: transform var(--duration-base) var(--ease-standard);
	bottom: calc(12px + env(safe-area-inset-bottom));
	z-index: 60;
	width: calc(100% - 2 * var(--page-margin));
	max-width: 416px;
	display: flex;
	align-items: center;
	justify-content: space-between;
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	/* Full pill + softer/tighter shadow (was --radius-xl 20px + --shadow-lg
	   0 8px 24px 0.14, matching this exact file's OLD "comprar" redesign) —
	   synced 2026-07-26 to Boom Home.dc.html's updated bar, which pairs
	   with the new circular CTA below; no existing token matches the new
	   shadow value exactly, hardcoded per that file. */
	border-radius: var(--radius-pill);
	box-shadow: 0 6px 18px rgba(31, 27, 46, 0.10);
	padding: 9px 10px;
}
/* Scale value + direction-based thresholds match Boom Home.dc.html's own
   scroll-linked bottomBarScale exactly (0.82 while scrolling down past a
   4px deadzone, back to 1 while scrolling up or within 40px of the top —
   see initBottomNavScrollScale(), boom.js) — was scale(0.94) with no
   deadzone/near-top override until synced 2026-07-25. */
.boom-bottomnav.is-scrolling { transform: translateX(-50%) scale(0.82); }
.boom-nav-item {
	position: relative;
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	gap: 2px;
	color: var(--color-text-muted);
	font-size: 26px;
	background: none; border: none;
	/* Small, fixed padding/radius so the active pill below has a shape to
	   fill — present at rest too (background stays transparent until
	   .is-active) so toggling active never shifts the icon's own position
	   or the row's total width. Deliberately modest and uniform (not
	   desktop's 11px/12px): 5 icon-only items already share a tight row
	   next to the floating "comprar" CTA — 6px 8px overflowed the bar by
	   ~1.3px on a real 320px viewport (confirmed via getBoundingClientRect,
	   not just eyeballed); plain 6px on all sides clears it with margin to
	   spare, re-verified live down to 320px. */
	padding: 6px;
	border-radius: var(--radius-sm);
}
.boom-nav-item:hover { color: var(--color-text-brand); }
/* Nav items are real <a> tags, so the global a:hover { text-decoration:
   underline } rule (line 51) applies to them too, unless overridden — its
   specificity (element+pseudo, 0,0,1,1) is actually LOWER than a single
   class+pseudo like this one (0,0,2,0), so this plain override is enough,
   no !important needed. Covers hover/focus/active — "click" on a touch
   device usually means one of these two stick around after the tap (user
   report + screenshot, 2026-07-27: nav items showing an underline that
   doesn't belong on a button-styled nav row, only on inline text links). */
.boom-nav-item:hover,
.boom-nav-item:focus,
.boom-nav-item:focus-visible,
.boom-nav-item:active,
.boom-nav-cta:hover,
.boom-nav-cta:focus,
.boom-nav-cta:focus-visible,
.boom-nav-cta:active,
.boom-menu-sheet__item:hover,
.boom-menu-sheet__item:focus,
.boom-menu-sheet__item:focus-visible,
.boom-menu-sheet__item:active {
	text-decoration: none;
}
/* "Pushed"/current-page state (footer.php sets .is-active server-side for
   início/minha conta from real is_front_page()/is_shop()/is_account_page()
   conditionals; initCheckoutStepTracker(), boom.js, sets it for carrinho/
   pagar from real scroll position — see that function's own doc comment).
   Same tinted-pill background as desktop's own active/hover treatment
   (desktop-nav.css) — mobile never had this box shape before 2026-07-26,
   only a bare color change; the user asked for the same box look here
   too. */
.boom-nav-item.is-active {
	color: var(--color-text-brand);
	background: var(--color-bg-surface-tint);
}
/* Badge's own positioning root — see footer.php's comment on why this
   wrapper exists (keeps the badge pinned to the icon itself, not the
   whole nav item, once the desktop sidebar's hover-expand makes that a
   much wider box than the icon alone). */
.boom-nav-item__icon-wrap { position: relative; display: inline-flex; flex-shrink: 0; }
.boom-nav-item__badge {
	position: absolute; top: -6px; right: -8px;
	min-width: 16px; height: 16px; padding: 0 4px;
	display: inline-flex; align-items: center; justify-content: center;
	background: var(--color-text-brand); color: #fff;
	font: var(--font-caption); font-size: 11.7px; font-weight: var(--weight-bold);
	border-radius: var(--radius-pill);
}
/* Always rendered (see footer.php + functions.php boom_cart_badge_fragment) so
   WooCommerce's fragment replacement always has an element to target; hidden at 0. */
.boom-nav-item__badge.is-empty { display: none; }
.boom-nav-item--wa { color: var(--color-accent-whatsapp); }
/* "comprar" FAB — redesigned 2026-07-26 to Boom Home.dc.html's update: a
   62px circle (was a pill sized via transform:scale(1.35) on a smaller
   base) floating above the bar via negative margin, icon stacked over the
   label instead of side-by-side. Icon swapped rocket → bomb per the same
   mockup update. */
.boom-nav-cta {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 2px;
	width: 62px;
	height: 62px;
	background: var(--violet-600);
	color: #fff;
	border-radius: 50%;
	padding: 0;
	/* No exact token matches this exact spread/opacity — hardcoded per the
	   mockup, same precedent as the bar's own shadow above. */
	box-shadow: 0 6px 16px rgba(109, 40, 217, 0.38);
	margin: -22px -4px 0;
	flex-shrink: 0;
	transition: transform var(--duration-fast) var(--ease-standard), filter var(--duration-fast) var(--ease-standard);
}
.boom-nav-cta i { font-size: 25.2px; line-height: 1; } /* +20% over the mockup's own 21px, per request — no existing size token to bump a level instead, this is a literal hardcoded value like its sibling below */
.boom-nav-cta__label { font-size: 9.5px; font-weight: var(--weight-black); letter-spacing: 0.2px; line-height: 1; }
.boom-nav-cta:hover { color: #fff; filter: brightness(1.05); }
/* "Pushed" feel on tap — the mockup's own style-active hint
   (transform:scale(0.95)). Desktop's own shape (desktop-nav.css) repeats
   this same rule scoped to its own selector, since its plain transform:none
   base would otherwise win over this one there (more specific selector). */
.boom-nav-cta:active { transform: scale(0.95); }

/* ==========================================================================
   Footer (minimal for now)
   ========================================================================== */
.boom-footer {
	text-align: center;
	padding: var(--space-11) 0 var(--space-9);
	color: var(--color-text-secondary);
}
.boom-footer__brand { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--text-lg); color: var(--color-text-primary); }
.boom-footer__meta { font: var(--font-caption); font-size: var(--text-2xs); margin-top: var(--space-4); line-height: var(--leading-relaxed); }
.boom-footer__socials { display: flex; align-items: center; justify-content: center; gap: var(--space-6); margin-top: var(--space-5); }
.boom-footer__social {
	width: 26px; height: 26px;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	display: inline-flex; align-items: center; justify-content: center;
	color: var(--color-text-brand-deep);
}
.boom-footer__social--wa { color: var(--color-accent-whatsapp); }
.boom-footer__copy { font: var(--font-caption); font-size: var(--text-2xs); margin-top: var(--space-5); line-height: var(--leading-relaxed); }

/* ==========================================================================
   Pague com pix banner
   ========================================================================== */
.boom-pix-banner {
	background: var(--color-bg-surface);
	border: 0.5px solid var(--violet-200);
	border-radius: var(--radius-lg);
	padding: var(--space-6) var(--space-7);
}
.boom-pix-banner__head { display: flex; align-items: center; gap: 11px; margin-bottom: var(--space-2); }
.boom-pix-banner__icon {
	flex: 0 0 auto;
	display: inline-flex; align-items: center; justify-content: center;
}
.boom-pix-banner__icon i { color: var(--color-text-brand); font-size: 19.5px; }
.boom-pix-banner__head-text { flex: 1; min-width: 0; }
.boom-pix-banner__title { font: var(--weight-bold) var(--text-base) var(--font-display); color: var(--color-text-brand-deep); margin: 0; display: block; }
.boom-pix-banner__sub { font: var(--font-caption); font-size: 9.75px; color: var(--color-text-secondary); margin: 0; display: block; }
.boom-pix-banner__tiers {
	display: flex; gap: var(--space-4);
	margin-top: 18.2px;
}
.boom-pix-tier { flex: 1; background: var(--color-bg-surface-violet-50); border-radius: var(--radius-sm); padding: var(--space-4) var(--space-5); text-align: center; }
.boom-pix-tier__pct { font: var(--weight-black) var(--text-md) var(--font-body); color: var(--color-text-brand-deep); display: block; }
.boom-pix-tier__day { font: var(--font-caption); font-size: 9.75px; font-weight: var(--weight-semibold); color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: var(--tracking-eyebrow); margin-top: 0; display: block; }
.boom-pix-tier--weekend { background: var(--violet-600); position: relative; }
.boom-pix-tier--weekend .boom-pix-tier__pct { color: #fff; }
.boom-pix-tier--weekend .boom-pix-tier__day { color: var(--violet-100); }
.boom-pix-tier__badge {
	position: absolute; top: -6px; right: 6px;
	background: var(--pink-500); color: #fff;
	font-size: 9.1px; font-weight: var(--weight-bold);
	padding: 2px 6px; border-radius: var(--radius-pill);
}

/* ==========================================================================
   Monte seu pedido — order builder
   ========================================================================== */
.boom-builder {
	border: var(--border-selected);
	border-radius: var(--radius-lg);
	padding: var(--card-padding);
	background: var(--color-bg-surface);
	box-shadow: var(--shadow-md);
	scroll-margin-top: 74px;
}
.boom-builder__head {
	display: flex; align-items: center; gap: var(--space-4);
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-md);
	padding: var(--space-5) var(--space-7);
	margin-bottom: var(--space-6);
}
.boom-builder__icon {
	width: 24px; height: 24px;
	display: inline-flex; align-items: center; justify-content: center;
	background: var(--color-bg-surface); border-radius: var(--radius-sm);
	color: var(--color-text-brand); font-size: 16.9px;
	box-shadow: var(--shadow-xs);
}
.boom-builder__title { font: var(--weight-black) var(--text-base) var(--font-body); color: var(--color-text-brand-deep); letter-spacing: 0.2px; text-transform: uppercase; }

.boom-builder__steps {
	display: flex; align-items: center;
	position: sticky;
	top: 58.5px; /* boom-header's rendered height — stops the stepper under it while scrolling through the builder form */
	z-index: 10;
	background: var(--color-bg-surface);
	/* Bleeds out to .boom-builder's own 2px border on both sides (2026-07-26
	   request) — .boom-builder's padding (--card-padding) is what insets this
	   row from its border by default, same as every other child; canceling
	   it with a matching negative margin, then adding that same amount back
	   as this row's own padding, keeps the step circles/labels at the exact
	   same visual x-position while letting the row's own opaque background
	   reach all the way to (never over) the border — previously the border
	   was visible with a bare unfilled strip beside the sticky row instead.
	   Bottom spacing (was margin-bottom, transparent/outside the box) moved
	   to padding-bottom instead, still --space-7, so that gap is now part of
	   this row's own opaque box too — whatever scrolls up from below is
	   fully hidden under the sticky row the whole time, not visible for a
	   beat in what used to be a see-through margin gap. */
	margin: 0 calc(var(--card-padding) * -1);
	padding: var(--space-4) var(--card-padding) var(--space-7);
}
.boom-step { display: flex; flex-direction: column; align-items: center; gap: 4px; flex-shrink: 0; }
.boom-step__circle {
	width: 22px; height: 22px; border-radius: 50%;
	background: var(--violet-100); color: var(--color-text-muted);
	display: inline-flex; align-items: center; justify-content: center;
	font-size: 13px; font-weight: var(--weight-black);
	transition: background var(--duration-base) var(--ease-standard);
}
.boom-step__label { font-size: 9.75px; font-weight: var(--weight-bold); color: var(--color-text-muted); white-space: nowrap; }
.boom-step.is-current .boom-step__circle { background: var(--color-bg-surface); color: var(--color-text-brand); border: var(--border-selected); }
.boom-step.is-current .boom-step__label { color: var(--color-text-brand); }
.boom-step.is-done .boom-step__circle { background: var(--color-text-brand); color: #fff; }
.boom-step.is-done .boom-step__label { color: var(--color-text-brand); }
.boom-step__line { flex: 1; height: 2px; background: var(--violet-100); margin: 0 4px 14px; border-radius: 1px; transition: background var(--duration-base) var(--ease-standard); }
.boom-step.is-done + .boom-step__line { background: var(--color-text-brand); }

/* ---------------------------------------------------------------------
   Real #services-form markup (rendered server-side by boom-core's
   [product_categories_dropdown] shortcode — ids/classes are fixed by
   that shortcode and by the real home.js it ships with; do not rename
   them here, only skin them). Selectors below are scoped to
   .boom-builder-form so they can't leak onto any other #services-form
   usage elsewhere on the site.
   --------------------------------------------------------------------- */
.boom-builder-form #services-form { display: flex; flex-direction: column; }
/* Explicit order on every direct child (flex `order` requires ALL of them set,
   or whichever ones are left at the default 0 interleave with each other in
   plain DOM order — required_not_filled/error/accordion/button would jump
   above the moved secondary-input group otherwise) — this is what visually
   moves the secondary-input step above the link field (user request) without
   moving the link field itself in the DOM (see [[boommkt-feedback-no-js-relocation]]).
   boom.js's enhanceSelect()/enhanceSecondaryField() (initOrderBuilderPickerPopups)
   wrap #cat/#second_level/#sub-cat/#service_qty and whichever of
   .service_comments/.opcao_voto/.service_datetime_picker is relevant into new
   .boom-order-picker(--key) wrappers that become the actual direct children
   here, in the select/field's original DOM position — the modifier class is
   what lets this rule target each step individually. */
.boom-builder-form #services-form > .boom-order-picker--network { order: 1; }
.boom-builder-form #services-form > .boom-order-picker--second_level { order: 2; }
.boom-builder-form #services-form > .boom-order-picker--sub_cat { order: 3; }
.boom-builder-form #services-form > #boomcore-promo-home { order: 4; }
.boom-builder-form #services-form > .boom-order-picker--qty { order: 5; }
.boom-builder-form #services-form > .boom-order-picker--secondary { order: 6; }
.boom-builder-form #services-form > div.service_link { order: 7; }
.boom-builder-form #services-form > select#service_auto_timer { order: 8; }
.boom-builder-form #services-form > #required_not_filled { order: 9; }
.boom-builder-form #services-form > #service_link_error_message { order: 10; }
.boom-builder-form #services-form > #accordion-regras-info { order: 11; }
.boom-builder-form #services-form > .woocommerce-variation-add-to-cart { order: 12; }
/* Two more direct children end up in #services-form beyond the ones listed
   above, confirmed live (2026-07-27) after the reorder above was first
   deployed — both defaulted to order:0, which bunched them all at the very
   top of the form instead of staying beside their real position:
   - boom.js's initOrderBuilderPassoLabels() inserts a ".boom-builder__passo"
     caption directly before each step's box — :has(+ ...) ties each one to
     its own target's order value so it renders immediately above it, not
     grouped with the others.
   - initDisclaimerPlacement() (pre-existing, unrelated to this feature)
     relocates .boom-builder__disclaimer to right before the add-to-cart
     button — tying it to the same order as the button, with DOM order (it's
     inserted right before the button) breaking the tie correctly. */
.boom-builder-form #services-form > .boom-builder__passo:has(+ .boom-order-picker--network) { order: 1; }
.boom-builder-form #services-form > .boom-builder__passo:has(+ .boom-order-picker--second_level) { order: 2; }
.boom-builder-form #services-form > .boom-builder__passo:has(+ .boom-order-picker--qty) { order: 5; }
.boom-builder-form #services-form > .boom-builder__passo:has(+ .boom-order-picker--secondary) { order: 6; }
.boom-builder-form #services-form > .boom-builder__passo:has(+ div.service_link) { order: 7; }
.boom-builder-form #services-form > .boom-builder__disclaimer { order: 12; }
/* A third one, same bug, same fix — caught live (2026-07-27) right after the
   first two above shipped: enhanceSecondaryField() (boom.js) now moves the
   real "exemplo de..." helper trigger to be a direct #services-form child
   too (a sibling right after whichever .boom-order-picker--secondary is
   relevant, not inside its popup — see that function's own comment), and it
   defaulted to order:0 same as the others did, jumping to the very top of
   the page instead of sitting under its own box. Adjacent-sibling `+` (not
   `:has(+ ...)` like the passo labels above) because this element comes
   AFTER the wrap, not before it. */
.boom-builder-form #services-form > .boom-order-picker--secondary + .home_services_form_popup_helper { order: 6; }
/* Spacing rhythm fix (user report + screenshot, 2026-07-27): in flex layout
   (#services-form is flex-direction:column), adjacent margins never
   collapse the way they would in normal block flow — so the wrap's own
   margin-bottom (var(--space-5), same as every other .boom-order-picker)
   PLUS the helper's own margin-top (var(--space-4), from the shared
   .home_services_form_popup_helper rule) were stacking into a bigger gap
   between the box and its helper than .service_link has to ITS OWN helper
   (which only ever has that single var(--space-4) — input and helper are
   both plain block children of one .service_link div, not flex siblings).
   Zeroing the wrap's margin here leaves the helper's own margin-top as the
   ONLY gap between box and helper, matching .service_link's rhythm exactly;
   the helper's own margin-bottom below re-establishes the standard
   step-to-step gap (var(--space-5), same as e.g. qty's box to "passo 4"'s
   caption) before the next caption. */
.boom-builder-form #services-form > .boom-order-picker--secondary { margin-bottom: 0; }
.boom-builder-form #services-form > .boom-order-picker--secondary + .home_services_form_popup_helper { margin-bottom: var(--space-5); }

/* Chevron-select rows: #cat, #second_level, #sub-cat, #service_qty, #service_auto_timer.
   All five are bare <select class="field">, no wrapper — the pill IS the select. */
.boom-builder-form select.field {
	display: block; width: 100%;
	appearance: none; -webkit-appearance: none;
	background-color: var(--color-bg-surface-tint);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7' fill='none'%3E%3Cpath d='M1 1L5.5 5.5L10 1' stroke='%236D28D9' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right var(--space-6) center;
	border: 2px solid transparent; border-radius: var(--radius-sm);
	padding: var(--space-5) 30px var(--space-5) var(--space-6);
	font: var(--weight-medium) var(--text-base) var(--font-body);
	color: var(--color-text-primary);
	margin-bottom: var(--space-5);
	cursor: pointer;
}
.boom-builder-form select.field:disabled { color: var(--color-text-muted); cursor: not-allowed; background-image: none; }
.boom-builder-form select.field:focus-visible { outline: 2px solid var(--color-border-brand); outline-offset: 1px; }

/* Custom combobox overlay — JS-enhanced (boom.js initOrderBuilderComboboxes) replacement
   for the native <select> popup on #cat/#second_level/#sub-cat/#service_qty/#service_auto_timer.
   A native <select> popup is OS-rendered: it can't show per-option icons and most browsers
   won't let CSS remove the native checkmark or restyle the selected row, which the design
   requires (icons for network options, a lighter fill instead of a checkmark for the
   selected row) — so those two asks are only achievable with a fully custom listbox.
   The real <select> stays in the DOM, visually hidden but still the source of truth: this
   layer only sets its value and dispatches a real 'change' event, exactly like the existing
   restore-selection code in home.js does ($("#cat").val(cat).change()) — the AJAX cascade,
   quantity filtering, etc. in home.js are untouched. */
.boom-builder-form select.field.boom-combobox-native {
	position: absolute;
	width: 1px; height: 1px;
	padding: 0; margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}
.boom-order-picker { position: relative; margin-bottom: var(--space-5); }
.boom-order-picker__trigger {
	display: flex; align-items: center; gap: var(--space-4);
	width: 100%;
	background-color: var(--color-bg-surface-tint);
	border: 2px solid transparent; border-radius: var(--radius-sm);
	padding: var(--space-3) 30px var(--space-3) var(--space-4);
	font: var(--weight-medium) var(--text-base) var(--font-body);
	color: var(--color-text-primary);
	text-align: left;
	cursor: pointer;
	position: relative;
}
.boom-order-picker__trigger-chevron {
	position: absolute; top: 50%; right: var(--space-6);
	transform: translateY(-50%);
	font-size: 11px; color: var(--color-text-brand);
}
.boom-order-picker__trigger:disabled,
.boom-order-picker__trigger[aria-disabled="true"] { color: var(--color-text-muted); cursor: not-allowed; }
.boom-order-picker__trigger:disabled .boom-order-picker__trigger-chevron,
.boom-order-picker__trigger[aria-disabled="true"] .boom-order-picker__trigger-chevron { display: none; }
.boom-order-picker__trigger:focus-visible { outline: 2px solid var(--color-border-brand); outline-offset: 1px; }

/* "monte seu pedido" step-input glow — a violet border + soft glow ring that
   pulses between --color-border-brand (violet-600) and --violet-300, shown on
   whichever step the customer needs to fill in next. .is-current is toggled
   by boom.js's initOrderBuilderStepGlow() — a separate, purely cosmetic layer
   from initOrderBuilderStepTracker()'s 1-2-3-4 circle indicator above the
   form (that one is untouched by this). One shared rule covers every step's
   box shape: a step's .boom-order-picker trigger (rede/serviço/quantidade/
   secondary-input, all popup-driven — see initOrderBuilderPickerPopups()),
   or a plain .field input (service_link, the one step that stays inline). */
.boom-order-picker.is-current .boom-order-picker__trigger,
.field.is-current,
.Zebra_DatePicker_Icon_Wrapper.is-current {
	border-color: var(--color-border-brand);
	box-shadow: 0 0 0 4px rgba(109, 40, 217, 0.12);
	animation: boom-pulse-step 1.8s ease-in-out infinite;
}
@keyframes boom-pulse-step {
	0%, 100% { border-color: var(--color-border-brand); }
	50% { border-color: var(--violet-300); }
}

.boom-order-picker__trigger-icon { flex-shrink: 0; font-size: 19.5px; color: var(--color-text-brand); }
.boom-order-picker__trigger-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.boom-order-picker__trigger-label.is-placeholder { color: var(--color-text-secondary); }

/* ==========================================================================
   "monte seu pedido" popup wizard — full-screen "passo N de X" popups
   (Boom Home.dc.html's networkPickerOpen/servicePickerOpen/qtyPickerOpen),
   replacing the old anchored combobox sheet. Same dark gradient chrome the
   design's picker popups use (linear-gradient(155deg,#3B2F5C,#1F1B2E) + white
   text + #C4B5FD icon color) — a deliberate fixed-dark surface independent of
   the page's light/dark theme toggle, not a token. Follows the site's
   standard popup conventions: shared backdrop/body-scroll-lock (registered in
   initPopupBackdrop()'s anyDialogOpen(), not a separate local backdrop —
   .boom-order-picker__popup itself is the full-viewport click-to-close
   target), mandatory always-visible scrollbar (CLAUDE.md #44, via
   [data-boom-popup-scrollbar-host]/initPopupScrollbar()), and mandatory
   two-tier width (#45 — mobile 90% here, desktop/tablet's own-base×1.2 rule
   lives in the consolidated block after .boom-pix-howto-popup).
   ========================================================================== */
.boom-order-picker__popup {
	display: none;
	position: fixed; inset: 0; z-index: 141;
	align-items: center; justify-content: center;
	padding: var(--page-margin);
	box-sizing: border-box;
}
.boom-order-picker__popup.is-open { display: flex; }
.boom-order-picker__card {
	width: 90%;
	max-height: min(560px, calc(100% - 2 * var(--page-margin)));
	background: linear-gradient(155deg, #3B2F5C, #1F1B2E);
	border-radius: var(--radius-md);
	box-shadow: 0 20px 50px rgba(0, 0, 0, 0.4);
	padding: var(--space-9);
	box-sizing: border-box;
	position: relative;
	display: flex; flex-direction: column;
	overflow: hidden;
	/* Forces its own compositing layer — defensive fix for a known WebKit
	   quirk where border-radius + overflow:hidden on a fractional (90%-of-
	   viewport) width can rasterize a child's own border unevenly per side. */
	-webkit-transform: translateZ(0); transform: translateZ(0);
}

/* Close-only, top-right (CLAUDE Design, 2026-07-28: the circular header back
   button was removed everywhere — "back" now lives only as the footer text
   row, .boom-order-picker__footer-back, gated by .has-back same as before). */
.boom-order-picker__nav {
	position: absolute; top: var(--space-6); right: var(--space-6); z-index: 2;
	display: flex; align-items: center; gap: 6px;
}
/* Own explicit `display` above ties the UA [hidden]{display:none} rule on
   specificity — needs its own override or setHelpMode's hideSharedClose
   (2026-07-29) can't actually hide it. Same recurring gotcha as every other
   .boom-order-picker__* element in this file (CLAUDE.md, "SSH-splice" §29
   sibling note — check here first before re-debugging it again). */
.boom-order-picker__nav[hidden] { display: none; }
.boom-order-picker__navbtn {
	display: flex; align-items: center; justify-content: center;
	width: 28px; height: 28px; padding: 0;
	background: rgba(255, 255, 255, 0.1);
	border: none; border-radius: 50%;
	color: #fff; font-size: 14px;
	cursor: pointer;
}
.boom-order-picker__navbtn:hover { background: rgba(255, 255, 255, 0.18); }
.boom-order-picker__card:not(.has-back) .boom-order-picker__footer-back { display: none; }

/* Step-progress row (rede→serviço→qtd.→[detalhes→]link), replacing the old
   "passo N de X" eyebrow text — boom.js's buildStepsHtml()/passoNumberFor().
   Right padding clears the absolutely-positioned close button above it. */
.boom-order-picker__steps {
	display: flex; align-items: center;
	padding-right: 34px;
	margin-bottom: var(--space-6);
	flex-shrink: 0;
}
.boom-order-picker__step {
	display: flex; flex-direction: column; align-items: center; gap: 3px;
	flex-shrink: 0;
}
.boom-order-picker__step-circle {
	width: 18px; height: 18px; flex-shrink: 0;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.25);
	display: flex; align-items: center; justify-content: center;
	font-size: 8.5px; font-weight: var(--weight-bold);
	color: rgba(255, 255, 255, 0.5);
}
.boom-order-picker__step.is-done .boom-order-picker__step-circle {
	background: #6D28D9; border-color: #6D28D9; color: #fff;
}
.boom-order-picker__step.is-done .boom-order-picker__step-circle i { font-size: 10px; }
.boom-order-picker__step.is-current .boom-order-picker__step-circle {
	border: 2px solid #A78BFA; color: #fff;
}
.boom-order-picker__step-label {
	font-size: 8px; font-weight: var(--weight-semibold); letter-spacing: 0.2px;
	color: rgba(255, 255, 255, 0.4); white-space: nowrap;
}
.boom-order-picker__step.is-done .boom-order-picker__step-label { color: rgba(255, 255, 255, 0.55); }
.boom-order-picker__step.is-current .boom-order-picker__step-label { color: #fff; }
.boom-order-picker__step-line {
	flex: 1; height: 1px; margin: 8px 3px 0;
	background: rgba(255, 255, 255, 0.18);
}
.boom-order-picker__step-line.is-done { background: #8B5CF6; }

.boom-order-picker__head {
	margin-bottom: var(--space-6);
	flex-shrink: 0;
}
.boom-order-picker__poptitle {
	display: block;
	font: var(--weight-bold) var(--text-lg) var(--font-display);
	color: #fff; line-height: 1.25;
}

/* Dedicated-wrapper scroll shape (CLAUDE.md #44) — this popup has persistent
   head (+ footer-back/confirm on some steps) chrome around the scroll area.
   margin-right cancels the card's own padding-right (--space-9) so the shared
   scrollbar track lands the mandatory ~6px from the popup's true edge. */
.boom-order-picker__scroll {
	display: flex; flex: 1; min-height: 0; flex-direction: column;
	position: relative; overflow: hidden;
	margin-right: calc(-1 * var(--space-9));
}
/* flex:1/min-height:0 for this specific host is set further down the file,
   after the shared [data-boom-popup-scrollbar-host] rule — see that rule's
   own comment (CLAUDE.md #44) for why the override must come textually after
   it (same selector specificity, so source order decides the tie). */
.boom-order-picker__list { padding-right: calc(var(--space-9) + 14px); }
.boom-order-picker__option {
	/* align-items:flex-start (was center) — a wrapped 2-3 line label (see
	   .boom-order-picker__option-label below) needs the checkmark/icon to sit
	   next to its FIRST line, not centered against the whole wrapped block. */
	display: flex; align-items: flex-start; gap: var(--space-3);
	width: 100%;
	background: none;
	border: none; border-bottom: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: var(--radius-sm);
	padding: var(--space-6) 0 /* var(--space-4) */;
	font: var(--weight-medium) var(--text-sm) var(--font-body);
	color: #fff;
	text-align: left;
	cursor: pointer;
}
.boom-order-picker__option:last-child { border-bottom: none; }
.boom-order-picker__option:hover,
.boom-order-picker__option:focus-visible { background: rgba(255, 255, 255, 0.08); }
.boom-order-picker__option-check { width: 10px; flex-shrink: 0; font-size: 12px; color: #fff; }
.boom-order-picker__option i { flex-shrink: 0; font-size: 14px; color: #C4B5FD; }
/* The list's first row is a bold "Passo N — ação" sentinel title now
   (CLAUDE Design, 2026-07-28), not a normal selectable option — no
   check/icon (boom.js's syncSelect() renders it with just one child span,
   .boom-order-picker__option-sentinel). */
.boom-order-picker__option.is-placeholder { padding: var(--space-4) 0; }
.boom-order-picker__option.is-placeholder:hover,
.boom-order-picker__option.is-placeholder:focus-visible { background: none; }
.boom-order-picker__option-sentinel {
	font: var(--weight-bold) var(--text-base) var(--font-body);
	color: #fff;
}
.boom-order-picker__option-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
/* Wraps onto multiple lines rather than truncating with an ellipsis (user
   report + screenshot, 2026-07-27: real category/product names routinely ran
   longer than the popup's own width and were cut mid-word, e.g. "Visualizações
   por 120 minutos em ...") — no name is ever shortened, it just takes the
   room it needs. */
.boom-order-picker__option-label { white-space: normal; word-break: break-word; }
.boom-order-picker__option-promo {
	display: flex; align-items: center; gap: 3px;
	font-size: 9.5px; font-weight: var(--weight-bold); color: #4ADE80;
	white-space: normal;
}
.boom-order-picker__option-promo i { color: #4ADE80; font-size: 10px; }

/* Dark-surface override for the shared scrollbar (boom.css's own
   .boom-popup-scrollbar/__thumb default to a light-surface tint) — same
   translucent-white treatment the old combobox scrollbar used, to read
   against this popup's dark gradient. */
.boom-order-picker__scroll .boom-popup-scrollbar { background: rgba(255, 255, 255, 0.12); }
.boom-order-picker__scroll .boom-popup-scrollbar__thumb { background: rgba(255, 255, 255, 0.6); }

.boom-order-picker__footer-back {
	display: flex; align-items: center; justify-content: center; gap: 6px;
	flex-shrink: 0;
	width: 100%; max-width: 100%; box-sizing: border-box;
	margin-top: var(--space-6);
	padding: var(--space-6) var(--space-7);
	background: none;
	/* 1px, not the previous 0.5px — sub-pixel border widths render
	   inconsistently across browsers/DPRs (a real, known WebKit rounding
	   issue, not this project's own layout math) and can round away to
	   nothing on one or more sides; 1px always renders as a real, visible
	   line. Opacity also bumped (0.25 → 0.4) for real contrast against this
	   popup's dark gradient — user report, 2026-07-29: the link-step
	   popup's own input/footer-back borders read as "missing" on a real
	   device screenshot. */
	border: 1px solid rgba(255, 255, 255, 0.4); border-radius: var(--radius-sm);
	cursor: pointer;
}
.boom-order-picker__footer-back i,
.boom-order-picker__footer-back span { font-size: var(--text-xs); font-weight: var(--weight-bold); color: #C4B5FD; }

/* Secondary-input step: no list — just the real field (moved in place, see
   boom.js's enhanceSecondaryField()) plus a centered, bold "continuar" button
   (mandatory popup-button rule) instead of instant row-tap auto-advance,
   since this step is free-typed rather than pick-from-a-list. Short, bounded
   content (one of 3 real fields) — no scrollbar mechanism needed, same
   carve-out CLAUDE.md #44 already gives other short fixed-length popups. */
.boom-order-picker__secondary-content { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.boom-order-picker__confirm {
	display: flex; align-items: center; justify-content: center;
	flex-shrink: 0;
	width: 100%;
	margin-top: var(--space-6);
	padding: var(--space-6);
	background: #6D28D9; color: #fff;
	border: none; border-radius: var(--radius-sm);
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	cursor: pointer;
}
.boom-order-picker__confirm:hover { filter: brightness(1.05); }
/* Same [hidden]-vs-own-display:flex gotcha as .steps/.head above — hidden
   while the secondary-input popup shows its own "exemplo de..." help view
   instead (enhanceSecondaryField()'s setSecondaryView()). */
.boom-order-picker__confirm[hidden] { display: none; }

/* [hidden] and this rule's own display:block share specificity (0,1,0 each) —
   same gotcha documented elsewhere in this file (e.g.
   .boom-phone-input__panel[hidden]) — needs an explicit override to win.
   The bold title itself is now hidden unconditionally for the 4 list-driven
   popups (boom.js's enhanceSelect(), user report 2026-07-27 — redundant with
   the list's own placeholder row) — shown for the secondary-input AND link
   steps (buildLinkStep(), 2026-07-28), the two popups with real prose instead
   of a list. */
.boom-order-picker__poptitle[hidden] { display: none; }
/* Same [hidden]-vs-own-display:X gotcha as .poptitle above — .steps and
   .head both set an explicit display, so setHelpMode() (boom.js) hiding
   them for a help view needs an explicit override to actually work. */
.boom-order-picker__steps[hidden],
.boom-order-picker__head[hidden] { display: none; }

/* Link step (step 4/5, buildLinkStep()) — a dual-surface add-on popup, not a
   replacement for the always-visible inline #service_link field (see that
   function's own doc comment). display:flex so whichever of the 3 views
   below is visible can size itself to the full available height — needed
   for the rules/example help views' own dedicated scroll mechanism
   (.boom-order-picker__help-scroll) to compute flex:1 correctly; "insira o
   link" itself stays short/bounded (CLAUDE.md #44's no-scrollbar carve-out,
   same as the secondary-input popup just above) so its own overflow-y:auto
   is just a safety net, not a real mandatory-scrollbar case. */
.boom-order-picker__link-content {
	flex: 1; min-height: 0;
	display: flex; flex-direction: column;
}
/* Three views, swapped via [hidden] (buildLinkStep()'s setView()) — never
   more than one visible at once. */
.boom-order-picker__link-view {
	display: flex; flex-direction: column; gap: var(--space-6);
	overflow-y: auto; -webkit-overflow-scrolling: touch;
}
/* [hidden] and this rule's own display:X share specificity (0,1,0 each) —
   same gotcha already documented on .boom-order-picker__poptitle[hidden]
   above — needs an explicit override to win, or a hidden view still renders
   (confirmed live, 2026-07-28: the link view stayed visible underneath the
   rules view instead of being replaced by it). */
.boom-order-picker__link-view[hidden] { display: none; }

/* "exemplo de X"/"ver regras" help view (buildHelpView(), boom.js) — light,
   reusing the REAL standalone popup's own classes as the styling source
   (user request, 2026-07-29: "the non-popup popups have to be the source"),
   not an invented parallel style. Two kinds, different real sources:
   .boom-order-picker__help-view--rules (.boom-service-rules-popup's own
   head-left/icon/title, a left-aligned icon BOX) and
   .boom-order-picker__help-view--example (the real #popup_servicos_home
   AJUDA skin's .boom-popup-skin__icon--info + bare h3.header — a plain
   centered icon, no circle/box). setHelpMode() (boom.js) hides the
   surrounding step-row/title chrome and switches the card to
   .boom-order-picker__card--light whenever one of these is showing.
   head/scroll/btn shape (CLAUDE.md #44, "the best popup model" —
   .boom-cashboom-popup): title area, then a dedicated scroll wrapper with
   the mandatory always-visible scrollbar, THEN the (shared, outside this
   view) footer-back "voltar" button — user report, 2026-07-29: the first
   draft just let content flow inside the wizard's own plain-overflow area,
   no real scrollbar.

   'rules' vs 'example' need DIFFERENT header treatment because their real
   sources differ (2026-07-29 follow-up, in response to "why doesn't the
   header fit on the same line as the X here, when it does in the non-popup
   version?"): .boom-service-rules-popup__head is a true in-flow row (icon+
   title+its OWN close button, justify-content:space-between) — buildHelpView()
   now builds that exact structure for 'rules' (with a real
   .boom-service-rules-popup__close button) instead of relying on the
   wizard's shared floating X, so it needs NO top clearance and the shared
   .boom-order-picker__nav is hidden while this view is showing
   (setHelpMode's hideSharedClose param). 'example' has no such in-row
   sibling in its own real source (#popup_servicos_home's AJUDA skin is a
   plain centered h3 with the shared corner close button, same shape the
   wizard's X already matches) so it keeps the old margin-top clearance. */
.boom-order-picker__help-view {
	display: flex; flex-direction: column;
	flex: 1; min-height: 0;
}
.boom-order-picker__help-view[hidden] { display: none; }
.boom-order-picker__help-view--example { margin-top: 40px; }
/* .boom-service-rules-popup__head/__head-left/__icon/__title/__close are all
   reused verbatim (boom.css, further up this file) — no override needed
   here; __head already carries its own margin-bottom/flex-shrink. */

/* text-align (not align-items) — centers the icon glyph/title's own inline
   content without shrinking .help-scroll's flex-child width, which needs
   to stay 100% for its scrollbar track to sit at the true right edge. */
.boom-order-picker__help-view--example { text-align: center; }
/* .boom-popup-skin__icon--info is already a fully unscoped rule (boom.css,
   further up this file) — reused as-is, no override needed. h3.header and
   #helper's own span.spacement/.lower_text treatment ARE scoped to their
   real ancestor (#popup_servicos_home:has(> #helper) ...) in their
   original CSS, so the same values are re-declared here, scoped to this
   view instead — same classes, same numbers, just copied content that's no
   longer inside that real container (see exampleTrigger's own doc comment,
   buildLinkStep()). */
.boom-order-picker__help-view--example h3.header {
	flex-shrink: 0;
	font: var(--weight-medium) var(--text-lg) var(--font-body);
	color: var(--color-text-primary);
	margin: 0 0 var(--space-4);
}
.boom-order-picker__help-view--example .boom-order-picker__help-body {
	font-size: var(--text-xs);
	color: var(--color-text-secondary);
	line-height: var(--leading-relaxed);
}
.boom-order-picker__help-view--example .boom-order-picker__help-body .spacement { display: block; margin-top: var(--space-3); }
.boom-order-picker__help-view--example .boom-order-picker__help-body .spacement:first-child { margin-top: 0; }
.boom-order-picker__help-view--example .boom-order-picker__help-body .lower_text {
	display: block;
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-sm);
	padding: var(--space-4) var(--space-6);
	margin: var(--space-3) 0 0;
	font-size: var(--text-xs);
	color: var(--color-text-brand-deep);
	text-decoration: none;
}
/* #shortDescription ('ver regras' real content) needs no override here —
   its own default styling (unscoped, see that rule's own comment) is
   already correct for a light surface, which is what this view now is. */

/* Dedicated scroll wrapper (CLAUDE.md #44) — mirrors
   .boom-service-rules-popup__scroll exactly (same --space-9 padding
   context, since .boom-order-picker__card uses the same token). */
.boom-order-picker__help-scroll {
	display: flex; flex: 1; min-height: 0; flex-direction: column;
	position: relative; overflow: hidden;
	margin-right: calc(-1 * var(--space-9));
}

/* "ver regras"/"exemplo de X" help views use the site's standard LIGHT
   modal colors (matching .boom-service-rules-popup and the real
   #popup_servicos_home helper skin) instead of this popup family's
   fixed-dark surface — toggled via .boom-order-picker__card--light
   (setHelpMode(), boom.js). User request, 2026-07-29: only the real wizard
   steps stay on the dark gradient; these are informational content, not a
   selection step, and should look like every other info popup on the site.
   border-top matches both real source popups exactly (.boom-service-rules-popup
   / .ui-dialog:has(#popup_servicos_home > #helper), both 4px solid the same
   brand color). footer-back becomes the same solid purple CTA every other
   light-surface popup button on the site uses (--color-bg-cta, tokens.css)
   instead of the dark family's bordered-outline pill — user report,
   2026-07-29 ("the bottom voltar button has to be purple as all other
   buttons in light background from this site are"). Only .navbtn (the X,
   still visible in a help view) needs its own light override —
   .poptitle/.steps' own dark styling never actually shows while this class
   is active, since setHelpMode() hides both at the same time. */
.boom-order-picker__card--light {
	background: var(--color-bg-surface);
	border-top: 4px solid var(--color-text-brand);
	box-shadow: 0 20px 50px rgba(0, 0, 0, 0.18);
}
.boom-order-picker__card--light .boom-order-picker__navbtn {
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
}
.boom-order-picker__card--light .boom-order-picker__navbtn:hover { background: var(--color-border-default); }
.boom-order-picker__card--light .boom-order-picker__footer-back {
	background: var(--color-bg-cta);
	border: none;
}
.boom-order-picker__card--light .boom-order-picker__footer-back i,
.boom-order-picker__card--light .boom-order-picker__footer-back span { color: #fff; }
.boom-order-picker__card--light .boom-order-picker__footer-back:hover { filter: brightness(1.05); }
.boom-order-picker__link-notice {
	display: flex; align-items: center; gap: 6px;
	font-size: 8.5px; font-weight: var(--weight-medium); color: #C4B5FD;
	line-height: 1.4;
}
.boom-order-picker__link-notice i { font-size: 14px; flex-shrink: 0; }
.boom-order-picker__link-input {
	width: 100%; max-width: 100%; box-sizing: border-box;
	/* min-width:0 overrides the flex item default of min-width:auto — without
	   it, a flex column child (.boom-order-picker__link-view is
	   display:flex;flex-direction:column) can refuse to shrink to its own
	   width:100%, overflowing the card instead (confirmed live 2026-07-28). */
	min-width: 0;
	background: rgba(255, 255, 255, 0.08);
	/* Opacity bumped 0.14 → 0.4 — real contrast against this popup's dark
	   gradient background; user report, 2026-07-29: read as a "missing"
	   border on a real device screenshot. */
	border: 1px solid rgba(255, 255, 255, 0.4);
	border-radius: var(--radius-sm);
	padding: var(--space-5) var(--space-6);
	font: var(--weight-medium) var(--text-sm) var(--font-body);
	color: #fff;
}
.boom-order-picker__link-input::placeholder { color: rgba(255, 255, 255, 0.4); }
.boom-order-picker__link-input:focus-visible { outline: 2px solid #A78BFA; outline-offset: 1px; }
.boom-order-picker__link-footer { flex-shrink: 0; margin-top: var(--space-6); }
.boom-order-picker__link-submit {
	display: flex; align-items: center; justify-content: center; gap: 7px;
	width: 100%;
	background: linear-gradient(135deg, #7C3AED, #5B21B6); color: #fff;
	border: none; border-radius: var(--radius-sm);
	padding: var(--space-6); box-sizing: border-box;
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	cursor: pointer; margin-bottom: var(--space-5);
}
.boom-order-picker__link-submit:hover { filter: brightness(1.05); }
/* Dark-popup overrides for the cloned real payment-icons row
   (.boom-builder__payments, order-builder.php) — same idea as the
   .boom-order-picker__rules-trigger override just above: the light-surface
   tokens it uses by default read wrong against this popup's fixed-dark card. */
.boom-order-picker__card .boom-builder__payments { margin-top: 0; }
.boom-order-picker__card .boom-builder__payments-label { color: #C4B5FD; }
.boom-order-picker__card .boom-pay-chip { background: rgba(255, 255, 255, 0.1); color: #fff; }

/* Dev-preview-only "digite seu @" feed-finder card (buildLinkStep(), boom.js)
   — .boom-dev-preview__tag is the existing sitewide dev-preview badge
   (page-minha-conta.php's own "prévia interna" cards, tokens.css's
   --violet-700), reused as-is; only this card's own content styling is new. */
.boom-order-picker__feedfinder {
	position: relative;
	display: flex; align-items: center; gap: var(--space-4);
	background: rgba(255, 255, 255, 0.08);
	border: 1px solid rgba(255, 255, 255, 0.14);
	border-radius: var(--radius-sm);
	padding: var(--space-5) var(--space-6);
	cursor: pointer;
}
.boom-order-picker__feedfinder-icon {
	width: 26px; height: 26px; flex-shrink: 0;
	border-radius: 50%;
	background: linear-gradient(135deg, #7C3AED, #6D28D9);
	display: flex; align-items: center; justify-content: center;
}
.boom-order-picker__feedfinder-icon i { font-size: 14px; color: #fff; }
.boom-order-picker__feedfinder-text { flex: 1; min-width: 0; }
.boom-order-picker__feedfinder-title { display: block; font-size: 9.5px; font-weight: var(--weight-bold); color: #fff; }
.boom-order-picker__feedfinder-sub { display: block; font-size: 8px; color: #C4B5FD; margin-top: 1px; }
.boom-order-picker__feedfinder-chevron { font-size: 14px; color: #C4B5FD; flex-shrink: 0; }

/* Promo slot (module "promotions") — hidden until populated. Mockup (Boom Home.dc.html
   L295-304, selectedServicePromo/selectedQtyPromo) styles this as a plain inline row —
   no background box — not the boxed "badge" treatment used elsewhere on the page. */
/* margin-top cancels delivery-time's own --space-5 margin-bottom below it (flex
   children don't collapse margins), netting --space-1 between the two notes. */
.boom-builder-form #boomcore-promo-home:not(:empty) {
	margin-top: calc(var(--space-1) - var(--space-5));
	margin-bottom: var(--space-5);
}
.promocao-inner {
	display: flex; align-items: center; gap: var(--space-3);
	color: var(--color-text-success);
	font-size: 11.7px; font-weight: var(--weight-bold); /* matches .boom-builder__delivery-time's font-size */
	padding: 2px 2px var(--space-4) 0; line-height: var(--leading-normal); /* no left inset — flush with delivery-time */
}
.promocao-inner::before {
	content: '\ee7c'; /* Tabler "ti-discount-2" glyph (verified against the loaded webfont's own CSS) */
	font-family: 'tabler-icons' !important; font-size: 13px; flex-shrink: 0; color: var(--color-text-success); /* matches .boom-builder__delivery-time::before's icon size so both rows' glyph widths (and the text after them) line up */
}

/* Text rows: each wrapping div holds an input/textarea (.field) plus a "helper" tooltip
   trigger as siblings. The design shows the helper ("exemplo do link" etc.) as a plain row
   BELOW the pill, not inside it — so the tint/padding/radius goes on the .field itself
   (the first child), not the wrapper, leaving the helper to sit underneath with its own
   margin-top and no shared background. Covers .service_link, .service_comments, .opcao_voto,
   .service_datetime_picker. */
.boom-builder-form div.service_link,
.boom-builder-form div.service_comments,
.boom-builder-form div.opcao_voto,
.boom-builder-form div.service_datetime_picker {
	margin-bottom: var(--space-5);
}
/* Unavailable-service look, same treatment on all four wrapped fields — home.js's
   fill_quantity_selector() adds .disabled to service_comments/opcao_voto/
   service_datetime_picker alongside service_link's own disable_service_link()
   when a selected service has zero purchasable variations. The helper icon is a
   sibling inside the same wrapper, so it dims with the row and additionally
   loses pointer-events so it can't be tapped open on a field that's disabled. */
.boom-builder-form div.service_link.disabled,
.boom-builder-form div.service_comments.disabled,
.boom-builder-form div.opcao_voto.disabled,
.boom-builder-form div.service_datetime_picker.disabled { opacity: 0.55; }
.boom-builder-form div.service_link.disabled .field,
.boom-builder-form div.service_comments.disabled .field,
.boom-builder-form div.opcao_voto.disabled .field,
.boom-builder-form div.service_datetime_picker.disabled .field { cursor: not-allowed; }
.boom-builder-form div.service_link.disabled .home_services_form_popup_helper,
.boom-builder-form div.service_comments.disabled .home_services_form_popup_helper,
.boom-builder-form div.opcao_voto.disabled .home_services_form_popup_helper,
.boom-builder-form div.service_datetime_picker.disabled .home_services_form_popup_helper {
	pointer-events: none;
}
/* Same disabled treatment as the rule above, mirrored onto the secondary-
   input popup's own trigger box + (now-external) helper — enhanceSecondaryField()'s
   wrap/helperEl are SIBLINGS of div.service_comments/.opcao_voto/
   .service_datetime_picker now (the popup wizard, boom.js), not descendants,
   so they don't inherit the rule above by cascade the way the always-inline
   service_link box still does. User report, 2026-07-29: opção de voto's own
   trigger/helper didn't look disabled the way the link field's did. */
.boom-order-picker--secondary.is-disabled .boom-order-picker__trigger { opacity: 0.55; cursor: not-allowed; }
.home_services_form_popup_helper.is-disabled { opacity: 0.55; pointer-events: none; }
/* service_auto_timer isn't wrapped in its own div (bare <select>, no helper) —
   style its own :disabled state directly instead of a wrapper .disabled class. */
.boom-builder-form select#service_auto_timer:disabled { opacity: 0.55; cursor: not-allowed; }

.boom-builder-form .service_link > .field,
.boom-builder-form .service_comments > .field,
.boom-builder-form .opcao_voto > .field {
	display: block; width: 100%;
	background: var(--color-bg-surface-tint);
	border: 2px solid transparent; outline: none; resize: none;
	border-radius: var(--radius-sm);
	padding: var(--space-5) var(--space-6);
	font: var(--weight-medium) var(--text-base) var(--font-body);
	color: var(--color-text-primary);
	margin: 0;
}
.boom-builder-form textarea.field { min-height: 60px; line-height: var(--leading-normal); resize: vertical; }
.boom-builder-form .field::placeholder { color: var(--color-text-secondary); }

/* service_datetime_picker's .field isn't a direct child (Zebra DatePicker — the real
   library behind this input — nests it inside its own <span class="Zebra_DatePicker_Icon_Wrapper">
   and sets that span's display/width/padding inline via JS, measured while the field is
   still our default display:none for conditional fields, so it measures 0 and the input
   collapses to ~16px with zero padding). Old theme's real, working CSS (shoptimizer-b/
   style.css) fixes the collapse the same way: force the wrapper's box back with
   !important on every property JS sets inline, since only !important beats that. Padding
   specifically must match !important too — a first pass here left it without, so the
   inline `padding: 0` from Zebra's JS was silently winning and the field rendered ~14px
   tall against the other fields' 34px. The pill background/padding also goes on this
   wrapper (not the outer .service_datetime_picker div) so the helper row below renders
   outside it. */
.boom-builder-form .service_datetime_picker > .Zebra_DatePicker_Icon_Wrapper {
	display: block !important;
	width: 100% !important;
	/* Right side wider than the base --space-6 (user report + screenshot,
	   2026-07-27): the calendar icon sits at right:var(--space-6) with its own
	   real glyph width on top of that, so a symmetric padding lets long
	   placeholder text (e.g. "Selecione data e horário (de Brasília / GMT
	   -3)") render underneath/behind the icon instead of stopping short of it.
	   34px clears the icon's own box with a small buffer to spare. */
	padding: var(--space-5) 34px var(--space-5) var(--space-6) !important;
	background: var(--color-bg-surface-tint);
	border: 2px solid transparent;
	border-radius: var(--radius-sm);
	box-sizing: border-box;
}
.boom-builder-form .service_datetime_picker .field {
	display: block; width: 100%;
	background: none; border: none; outline: none;
	font: var(--weight-medium) var(--text-base) var(--font-body);
	color: var(--color-text-primary);
	padding: 0; margin: 0;
}
/* The placeholder string itself ("Selecione data e horário (de Brasília /
   GMT -3)") is long enough that even with the icon-clearing padding above,
   it still doesn't fit on the field's one line at the base font-size inside
   this popup's narrower card — confirmed by measuring its real rendered
   width against the field's real content-box width (353px vs 295px
   available at 16px; fits with room to spare at 12.5px, ~276px). A real
   <input> can never wrap (user's "line break" suggestion isn't achievable
   for this specific element), so this is the actual fix: shrink only the
   placeholder's own font-size via ::placeholder, which is independent of
   the real value's font-size — once a date is picked, the short resulting
   value ("29/Jul/2026 18:30") renders at the normal size, unaffected. */
.boom-builder-form .service_datetime_picker .field::placeholder {
	font-size: 12.5px;
}
.boom-builder-form .Zebra_DatePicker_Icon {
	top: 50% !important;
	right: var(--space-6) !important;
	transform: translateY(-50%);
}

/* passo 1–4 labels above each real field — purely cosmetic text inserted by
   boom.js (initOrderBuilderPassoLabels), matching the Claude Design mockup's
   "passo N — ..." captions. Not part of the shared boom-core shortcode markup. */
.boom-builder-form .boom-builder__passo {
	font-size: 11.7px; font-weight: var(--weight-medium); color: var(--color-text-secondary);
	margin-bottom: var(--space-3);
}

/* "tempo de entrega: em breve" note under passo 2 (boom.js's initDeliveryTimeNote) —
   placeholder copy today, see that function's TODO for the future monitoring-baseline
   swap. Sits where the design's inline hint rows do: small, icon-led, no background box. */
/* --color-text-brand-deep (violet-700, #4C1D95) — the project's confirmed brand purple
   (tokens.css labels --violet-600 "primary brand violet"; -deep is the same hue, just the
   darker step already used for text-on-light legibility elsewhere, e.g. this same icon
   and #shortDescription's info-circle hints). Text and icon share one color, same
   single-color-for-icon+text convention as .promocao-inner (green) elsewhere in this file
   — was gray text + violet icon before, which read as a generic muted hint rather than a
   BOOM-branded one. */
.boom-builder-form .boom-builder__delivery-time {
	display: flex; align-items: center; gap: var(--space-3);
	font-size: 11.7px; font-weight: var(--weight-medium); color: var(--color-text-brand-deep);
	margin: calc(var(--space-3) * -1) 0 var(--space-5);
}
.boom-builder-form .boom-builder__delivery-time::before {
	content: '\ea70'; /* Tabler "ti-clock" glyph (verified against the loaded webfont's own CSS, same convention as .promocao-inner::before) */
	font-family: 'tabler-icons' !important; font-size: 13px; flex-shrink: 0; color: var(--color-text-brand-deep);
}

/* WooCommerce core (add-to-cart.js AddToCartHandler.updateButton) inserts a
   "Ver carrinho" <a class="added_to_cart wc-forward"> right after any button
   whenever the real 'added_to_cart' body event fires — which home.js triggers
   on every successful add so other fragments (cart badge) refresh. That link
   isn't part of this design, so it's suppressed visually without touching the
   event pipeline the badge refresh depends on. */
.boom-builder-form .added_to_cart.wc-forward { display: none; }

.boom-builder-form .home_services_form_popup_helper {
	display: flex; align-items: center; gap: 5px;
	margin-top: var(--space-4);
	color: var(--color-text-brand);
	font-size: 10.4px;
	cursor: help;
}
.boom-builder-form .home_services_form_popup_helper i { font-size: 13px; }
.boom-builder-form .home_services_form_popup_helper span.helper { text-decoration: underline; }
/* Dark-popup context override — the secondary-input step now renders this
   trigger inside .boom-order-picker__popup's dark gradient card (see
   enhanceSecondaryField(), boom.js), where the light-surface violet above
   reads too dark to have real contrast. */
.boom-order-picker__secondary-content .home_services_form_popup_helper { color: #C4B5FD; }
.boom-order-picker__secondary-example { margin-top: var(--space-5); }

/* Fields hidden until home.js shows the one relevant to the selected service —
   matches production's default-hidden state (previously missing here, which
   left every conditional field visible at once). */
.boom-builder-form .service_comments,
.boom-builder-form select#service_auto_timer,
.boom-builder-form .opcao_voto,
.boom-builder-form .service_datetime_picker,
.boom-builder-form #required_not_filled,
.boom-builder-form #service_link_error_message {
	display: none;
}

.boom-builder-form #required_not_filled {
	text-align: center; font-size: 10.4px; font-weight: var(--weight-bold);
	color: var(--pink-500); margin: 0 0 var(--space-5);
}
.boom-builder-form #required_not_filled.required_field_not_filled {
	display: block;
	animation: boom-blink-text 0.5s step-end infinite alternate;
}
.boom-builder-form #service_link_error_message {
	text-align: center; border-radius: var(--radius-sm);
	padding: var(--space-5) var(--space-6); margin-bottom: var(--space-5);
	font-size: var(--text-xs); font-weight: var(--weight-semibold);
	color: var(--pink-500); background: rgba(225, 29, 72, 0.06);
}
.boom-builder-form .required-error {
	animation: boom-blink-border 0.5s step-end infinite alternate;
	border: 1px solid transparent;
}
@keyframes boom-blink-border { 50% { border-color: var(--pink-500); background-color: rgba(225, 29, 72, 0.1); } }
@keyframes boom-blink-text { 50% { color: transparent; } }

/* "ver regras e informações do serviço" — was a checkbox-driven inline
   accordion; converted 2026-07-28 (CLAUDE Design) into a trigger button that
   opens a shared popup instead (.boom-service-rules-popup below,
   initServiceRulesPopup() in boom.js, which reparents #shortDescription's
   real content — wpwm_b_product_meta.regras_e_informacoes — into that popup;
   the div itself is never rebuilt, only relocated). #accordion-regras-info
   stays as the trigger's positioning container (order:11 rule above still
   targets this id) — .content's OWN accordion CSS is gone; the popup now
   owns all of #shortDescription's layout/spacing via .boom-service-rules-popup__body. */
.boom-builder-form #accordion-regras-info { padding: var(--space-5) 0; margin-bottom: var(--space-1); }
.boom-order-picker__rules-trigger {
	display: inline-flex; align-items: center; gap: 5px;
	background: none; border: none; padding: 0;
	color: var(--color-text-brand-deep);
	font-size: 11.7px; font-weight: var(--weight-medium);
	cursor: pointer;
}
.boom-order-picker__rules-trigger i { font-size: 13px; }
.boom-order-picker__rules-trigger span { text-decoration: underline; }
/* Dark-popup context override — the link-step popup's own duplicate trigger
   (boom.js) lives inside .boom-order-picker__popup's dark gradient card,
   same override pattern as .home_services_form_popup_helper just above. */
.boom-order-picker__card .boom-order-picker__rules-trigger { color: #C4B5FD; }

/* #shortDescription is filled at runtime by home.js from the selected product's real
   wpwm_b_product_meta.regras_e_informacoes (rich text: <p>/<li>/<b>/<a>); it also
   prepends a Font Awesome info-circle icon to every <p> itself (home.js line ~522),
   so we skin that icon + the row rhythm rather than re-adding our own icon markup.
   Unscoped (was .boom-builder-form #shortDescription) — initServiceRulesPopup()
   (boom.js) reparents this real node into .boom-service-rules-popup, outside
   .boom-builder-form entirely, on first open; the ID is already unique sitewide
   so scoping to its old ancestor was never load-bearing, just consistency with
   the rest of this file's #services-form rules. */
#shortDescription { display: flex; flex-direction: column; gap: var(--space-5); }
#shortDescription p {
	display: flex; align-items: flex-start; gap: 5px;
	font-size: var(--text-2xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed);
	margin: 0;
}
#shortDescription p i.fa-info-circle { color: var(--color-text-brand-deep); font-size: 14.3px; flex-shrink: 0; margin-top: 1px; }
#shortDescription ul,
#shortDescription ol {
	margin: 0; padding-left: 16px;
	display: flex; flex-direction: column; gap: var(--space-3);
}
/* Real regras_e_informacoes content commonly uses bare <li> siblings with no <ul>
   wrapper (confirmed in the actual "visualizações nos stories" product data) — give
   li its own indent/marker color rather than relying on a parent list container. */
#shortDescription li {
	list-style-position: outside; margin-left: 16px;
	font-size: var(--text-2xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed);
}
#shortDescription li::marker { color: var(--color-text-brand-deep); }
#shortDescription b,
#shortDescription strong { color: var(--color-text-primary); font-weight: var(--weight-semibold); }
#shortDescription a { color: var(--color-text-brand); text-decoration: underline; }

/* "ver regras e informações do serviço" popup (initServiceRulesPopup(),
   boom.js) — same standard-modal head/scroll/footer shape as
   .boom-cashboom-popup (CLAUDE.md #44), since the real per-product content
   (#shortDescription above) can run long. Two-tier width (#45) added to the
   consolidated block after .boom-pix-howto-popup, not here. */
.boom-service-rules-popup {
	display: none;
	position: fixed; z-index: 145;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	max-height: min(560px, calc(100% - 2 * var(--page-margin)));
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl);
	border-top: 4px solid var(--color-text-brand);
	padding: var(--space-9);
	box-sizing: border-box;
	box-shadow: var(--shadow-xl);
	flex-direction: column;
	overflow: hidden;
}
.boom-service-rules-popup.is-open { display: flex; }
.boom-service-rules-popup__scroll { display: flex; flex: 1; min-height: 0; flex-direction: column; position: relative; overflow: hidden; margin-right: calc(-1 * var(--space-9)); }
.boom-service-rules-popup__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-6); flex-shrink: 0; }
.boom-service-rules-popup__head-left { display: flex; align-items: center; gap: var(--space-4); min-width: 0; }
.boom-service-rules-popup__icon {
	width: 32px; height: 32px; flex-shrink: 0;
	border-radius: var(--radius-md);
	background: var(--color-bg-surface-tint);
	display: flex; align-items: center; justify-content: center;
}
.boom-service-rules-popup__icon i { font-size: 16px; color: var(--color-text-brand); }
.boom-service-rules-popup__title { font: var(--font-section-title); font-size: var(--text-base); color: var(--color-text-brand-deep); }
.boom-service-rules-popup__close {
	width: 24px; height: 24px; flex-shrink: 0;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	border: none; padding: 0; cursor: pointer;
}
.boom-service-rules-popup__close i { font-size: 16.9px; }
.boom-service-rules-popup__btn {
	flex-shrink: 0; width: 100%; margin-top: var(--space-6);
	background: var(--color-bg-cta); color: #fff;
	border: none; border-radius: var(--radius-md);
	padding: var(--space-6); box-sizing: border-box;
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	text-align: center; cursor: pointer;
}
.boom-service-rules-popup__btn:hover { filter: brightness(1.05); }

.boom-builder-form .woocommerce-variation-add-to-cart { margin: 0; }
.boom-builder-form .single_add_to_cart_button {
	display: flex; width: 100%; align-items: center; justify-content: center; gap: 7px;
	font: var(--font-button);
	font-size: 16.38px; /* --text-sm (13.65px) + 20% */
	background: var(--color-bg-cta); color: #fff; border: none;
	border-radius: 10px;
	padding: 13px var(--space-9);
	box-shadow: var(--shadow-button);
	transition: transform var(--duration-fast) var(--ease-standard), filter var(--duration-fast) var(--ease-standard);
}
.boom-builder-form .single_add_to_cart_button:hover { filter: brightness(1.05); color: #fff; }
.boom-builder-form .single_add_to_cart_button:active { transform: scale(0.97); }
.boom-builder-form .single_add_to_cart_button:disabled {
	background: var(--violet-200); color: var(--color-text-muted); box-shadow: none; cursor: not-allowed;
}
.boom-builder-form .single_add_to_cart_button.loading { opacity: 0.7; cursor: wait; }

/* Two explicit rows (built server-side in front-page.php, split by field count) rather
   than one flex-wrap row — a wrap row breaks unpredictably mid-chip depending on exact
   pixel widths; splitting by field count keeps the layout the same regardless of viewport
   width, and stops the row from overflowing its container on narrower screens. */
.boom-builder__payments { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); margin-top: var(--space-6); margin-bottom: var(--space-5); }
.boom-builder__payments-row { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--space-4); max-width: 100%; }
.boom-builder__payments-label { font-size: 10.4px; color: var(--color-text-secondary); font-weight: var(--weight-semibold); }
.boom-pay-chip {
	display: inline-flex; align-items: center; gap: 5px;
	background: var(--color-bg-surface-tint); border-radius: var(--radius-sm);
	padding: 5px 8px; font-size: 10.4px; font-weight: var(--weight-bold); color: var(--color-text-primary);
}

.boom-builder__disclaimer { font-size: 10.4px; color: var(--color-text-secondary); text-align: center; margin: 0 0 var(--space-4); line-height: var(--leading-normal); }

.boom-builder__whatsapp {
	display: flex; align-items: center; justify-content: center; gap: 6px;
	background: var(--color-bg-surface-violet-50);
	border-radius: 9px;
	padding: 9px;
	margin-top: var(--space-5);
	font-size: var(--text-2xs); font-weight: var(--weight-bold); color: var(--color-text-brand-deep);
}
.boom-builder__whatsapp .ti-brand-whatsapp { color: #1E8E4F; font-size: 16.9px; }

/* "tem uma ideia de serviço ou sugestão?" CTA below "monte seu pedido" —
   the only trigger for this popup now (footer-trust.php's own duplicate
   copy removed 2026-07-25). green-100/green-800 on the "solicitar" pill
   (not white-on-#25D366) for the same WCAG contrast reason as
   .boom-popup-skin__btn--whatsapp. */
.boom-servico-cta__trigger {
	display: flex; align-items: center; gap: var(--space-4);
	width: 100%; box-sizing: border-box;
	background: linear-gradient(155deg, #241F38, #1F1B2E);
	border: none; border-radius: var(--radius-lg);
	padding: var(--space-6);
	cursor: pointer;
	text-align: left;
}
.boom-servico-cta__icon {
	width: 30px; height: 30px; flex-shrink: 0;
	border-radius: var(--radius-sm);
	background: rgba(255, 255, 255, 0.08);
	display: flex; align-items: center; justify-content: center;
}
.boom-servico-cta__icon i { font-size: 16px; color: var(--green-400); }
.boom-servico-cta__text { flex: 1; min-width: 0; }
.boom-servico-cta__title { display: block; font: var(--weight-bold) var(--text-base) var(--font-display); color: #fff; }
.boom-servico-cta__sub { display: block; font-size: var(--text-2xs); color: var(--violet-300); margin-top: 2px; }
.boom-servico-cta__cta {
	display: flex; align-items: center; gap: var(--space-3); flex-shrink: 0;
	background: var(--green-100); color: var(--green-800);
	border-radius: var(--radius-pill);
	padding: var(--space-4) var(--space-6);
	font-size: var(--text-2xs); font-weight: var(--weight-bold);
}
.boom-servico-cta__cta i { color: var(--green-800); font-size: 13px; }

/* ==========================================================================
   Help popup (jQuery UI dialog, built by home.js — #popup_servicos_home)
   and the link-add confirmation dialog it reuses. No CSS ships with
   boom-core for this, so the jQuery UI default chrome is fully re-skinned
   here to match the design system rather than left unstyled.
   ========================================================================== */
/* home.js initializes both dialogs (#popup_servicos_home, #cashboom_popup) with plain
   .dialog({ autoOpen:false, position:{...} }) — no modal:true — so jQuery UI never
   creates a .ui-widget-overlay backdrop element at all; the design's dimmed/blurred
   background behind these popups doesn't come from jQuery UI here. boom.js
   (initPopupBackdrop) creates and toggles a real .boom-popup-backdrop div itself,
   tracking whichever .ui-dialog is currently visible — clicks on it already close the
   popup for free via home.js's own existing "click outside closes" logic (a document
   mousedown handler that treats anything not inside #popup_servicos_home as outside). */
.boom-popup-backdrop {
	display: none;
	position: fixed; inset: 0; z-index: 90;
	background: rgba(15, 11, 26, 0.55);
	backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.boom-popup-backdrop.is-visible { display: block; }
/*
 * home.js initializes this dialog with jQuery UI's own position:{of:"#servicos", ...}
 * math, which computes document-relative top/left as inline styles — appropriate for
 * jQuery UI's native position:absolute default, but this is a mobile-first app where a
 * simple centered fixed overlay reads better and can't end up off-screen depending on
 * scroll position. top/left/transform are forced with !important to override whatever
 * home.js calculates inline.
 */
.ui-dialog {
	position: fixed !important; z-index: 91;
	top: 50% !important; left: 50% !important;
	transform: translate(-50%, -50%);
	width: min(360px, calc(100% - 2 * var(--page-margin))) !important;
	max-height: calc(100% - 2 * var(--page-margin));
	background: var(--color-bg-surface);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-xl);
	padding: var(--card-padding);
	overflow-y: auto;
}
.ui-dialog .ui-dialog-titlebar { display: none; }
#popup_servicos_home, #cashboom_popup {
	position: relative;
	font: var(--weight-regular) var(--text-sm) var(--font-body);
	color: var(--color-text-secondary);
	line-height: var(--leading-relaxed);
}
#popup_servicos_home .close-btn, #cashboom_popup .close-btn {
	position: absolute; top: -4px; right: -4px;
	width: 24px; height: 24px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	font-size: 14.3px; font-weight: var(--weight-bold);
	cursor: pointer;
}
#popup_servicos_home h3.header, #cashboom_popup h3.header {
	font: var(--weight-black) var(--text-md) var(--font-body);
	color: var(--color-text-brand-deep);
	margin: 0 var(--space-9) var(--space-6) 0;
}
#popup_servicos_home #helper p, #cashboom_popup #helper p { margin: 0 0 var(--space-4); }
/* home.js builds most helper content as bare <span>s (.spacement, or none) rather than
   <p>s — block them out and space them like paragraphs, matching production. */
#popup_servicos_home #helper span:not(#emoji_container *), #cashboom_popup #helper span:not(#emoji_container *) { display: block; }
#popup_servicos_home .spacement, #cashboom_popup .spacement { margin-top: var(--space-3); }
#popup_servicos_home .spacement:first-child, #cashboom_popup .spacement:first-child { margin-top: 0; }
#popup_servicos_home #helper img, #cashboom_popup #helper img {
	display: block; width: 100%; border-radius: var(--radius-md); margin-bottom: var(--space-5);
}
#popup_servicos_home .lower_text, #cashboom_popup .lower_text { display: block; margin-bottom: var(--space-3); }
/* PROJECT RULE: every popup/dialog button's text is centered and bold — `--font-button`
   already carries --weight-bold, so anywhere a button style overrides `font` or
   `font-weight` (e.g. for a full-width variant), re-declare `font-weight: var(--weight-bold)`
   and `text-align: center` explicitly rather than dropping to a lighter weight or
   left-aligned block text. Apply this to any new popup button style added later, not
   just the ones already on the page. */
#popup_servicos_home #botoes, #cashboom_popup #botoes { margin-top: var(--space-6); display: flex; justify-content: center; }
#popup_servicos_home #botoes a, #cashboom_popup #botoes a {
	display: inline-flex; align-items: center; justify-content: center;
	background: var(--color-bg-cta); color: #fff;
	font: var(--font-button);
	border-radius: var(--radius-pill);
	padding: var(--space-5) var(--space-9);
	box-shadow: var(--shadow-button);
	cursor: pointer;
}
#popup_servicos_home #botoes a:hover, #cashboom_popup #botoes a:hover { color: #fff; filter: brightness(1.05); }

/* Popup skin (boom.js initHelpPopupSkin) — matches the Claude Design mockup's card
   language for the real #popup_servicos_home popups home.js builds. Two distinct
   shapes, each scoped structurally (real ids unique to that flow, not a class toggled
   on/off elsewhere) so nothing here can leak onto the OTHER flows sharing this same
   container: a generic "ATENÇÃO" + message + "CHAMAR SUPORTE" popup, and a
   "CARREGANDO..." loading-spinner state. Both wrappers below only exist in the DOM
   for their one matching shape, and the next .empty() call (for ANY popup) clears
   them along with everything else. */

/* Shape 1 — the 4 in-form "AJUDA" helper tooltips (link, comments, opção de voto,
   date/time): #helper is unique to this shape. Centered icon/title/description; the
   link helper's normal case additionally gets a tinted box around its real example
   link(s) and copy relabeled to "exemplo do link" / "entendi" (see boom.js — the
   other 3 keep "AJUDA" since the design has no dedicated copy for them). */
.ui-dialog:has(#popup_servicos_home > #helper) { border-top: 4px solid #6D28D9; }
#popup_servicos_home:has(> #helper) { text-align: center; }
#popup_servicos_home:has(> #helper) .close-btn {
	top: -1px; right: -1px;
	width: auto; height: auto;
	background: none;
	font-size: 20.8px;
}
.boom-popup-skin__icon--info {
	display: block;
	font-size: 33.8px;
	color: var(--color-text-brand);
	margin: var(--space-4) 0 var(--space-4);
}
#popup_servicos_home:has(> #helper) h3.header {
	font: var(--weight-medium) var(--text-lg) var(--font-body);
	color: var(--color-text-primary);
	margin: 0 0 var(--space-4);
}
#popup_servicos_home:has(> #helper) #helper span.spacement {
	font-size: var(--text-xs);
	color: var(--color-text-secondary);
	line-height: var(--leading-relaxed);
}
/* Real example content is a bare <span class="lower_text"> and/or <a class="lower_text">
   — sometimes more than one (e.g. "@handle" AND a full URL as two example forms) —
   so each becomes its own tinted pill rather than JS wrapping them into one box. */
#popup_servicos_home:has(> #helper) .lower_text {
	display: block;
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-sm);
	padding: var(--space-4) var(--space-6);
	margin: var(--space-3) 0 0;
	font-size: var(--text-xs);
	color: var(--color-text-brand-deep);
	text-decoration: none;
}
#popup_servicos_home:has(> #helper) #botoes { display: block; margin-top: var(--space-6); }
#popup_servicos_home:has(> #helper) #botoes a {
	display: block; width: 100%;
	text-align: center;
	border-radius: var(--radius-md);
	padding: var(--space-6);
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	box-shadow: none;
}

/* Shape 2 — the real add-to-cart link/post confirmation ("confira os dados do post"):
   #link_preview is unique to this flow. All content (thumbnail, caption, stats, link)
   is real scraped data already in the DOM (home.js popup_confirmacao_de_link()) — this
   only restyles it, nothing here invents fields the real system doesn't provide. */
.ui-dialog:has(#popup_servicos_home > #link_preview) { border-top: 4px solid #6D28D9; }
#popup_servicos_home:has(> #link_preview) .close-btn {
	top: -1px; right: -1px;
	width: auto; height: auto;
	background: none;
	font-size: 20.8px;
}
.boom-popup-skin__head {
	display: flex; align-items: center; gap: var(--space-3);
	margin: 0 var(--space-9) var(--space-6) 0;
}
.boom-popup-skin__head h3.header { margin: 0; }
.boom-popup-skin__icon--warning { flex-shrink: 0; font-size: 23.4px; color: #F59E0B; }
#popup_servicos_home:has(> #link_preview) h3.header {
	font: var(--weight-bold) var(--text-md) var(--font-body);
	color: var(--color-text-primary);
}
#popup_servicos_home #link_preview {
	position: relative;
}
/* Placeholder frame shown while the thumbnail is being fetched — home.js adds
   .is-loading before calling getDataUri() and removes it once that call resolves
   (success or failure). */
#popup_servicos_home #link_preview.is-loading:not(:has(img:not([hidden])))::before {
	content: "Carregando imagem...";
	display: flex; align-items: center; justify-content: center;
	width: 100%; aspect-ratio: 16 / 10;
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-md);
	margin-bottom: var(--space-6);
	font-size: var(--text-xs); color: var(--color-text-secondary);
}
/* Fallback frame shown once loading has finished without a usable image — either
   there was no thumbnail_url at all, or getDataUri() failed/returned something
   that wasn't a data:image/ URI. */
#popup_servicos_home #link_preview:not(.is-loading):not(:has(img:not([hidden])))::before {
	content: "";
	display: block; width: 100%; aspect-ratio: 16 / 10;
	background: var(--color-bg-surface-tint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='34' height='34' viewBox='0 0 24 24' fill='none' stroke='%23B7B2C4' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='18' height='18' rx='2'/%3E%3Ccircle cx='8.5' cy='8.5' r='1.5'/%3E%3Cpath d='M21 15l-5-5L5 21'/%3E%3C/svg%3E") no-repeat center;
	border-radius: var(--radius-md);
	margin-bottom: var(--space-6);
}
/* Explicit "the thumbnail existed but genuinely failed to load" state
   (2026-07-19 user request) — home.js adds .boom-thumb-error once
   getDataUri() has failed even after its one built-in retry, distinct from
   the plain icon-only fallback above (which also covers the unrelated "no
   thumbnail_url at all" case). Repeats the fallback rule's own
   :not(:has(img:not([hidden]))) clause (redundant in practice — this class
   is only ever set once the img is already confirmed hidden — but needed
   so this selector's specificity (2 IDs, 3 classes/pseudo-classes, 1 type)
   actually exceeds the plain fallback's (2 IDs, 2 classes/pseudo-classes,
   1 type) instead of tying it: a bare ".boom-thumb-error:not(.is-loading)"
   measured equal specificity to the rule above (the "img" type selector
   buried inside :has() counts), which the source-order tiebreak alone
   didn't reliably win — confirmed live, the plain icon rendered instead of
   this text until the clause was added. Text comes from the
   data-boom-thumb-error-text attribute (home.js sets it from
   boomCoreAjax.i18n.imageLoadError), not hardcoded here, so it stays
   translatable per the project's i18n rule. */
#popup_servicos_home #link_preview.boom-thumb-error:not(.is-loading):not(:has(img:not([hidden])))::before {
	content: attr(data-boom-thumb-error-text);
	display: flex; align-items: center; justify-content: center;
	width: 100%; aspect-ratio: 16 / 10; box-sizing: border-box;
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-md);
	margin-bottom: var(--space-6);
	padding: var(--space-5);
	font-size: var(--text-xs); color: var(--color-text-secondary);
	text-align: center;
}
#popup_servicos_home #link_preview img:not([hidden]) {
	display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover;
	border-radius: var(--radius-md);
	margin-bottom: var(--space-6);
}
#popup_servicos_home #link_preview > span.lower_text {
	display: block;
	font-size: var(--text-xs); color: var(--color-text-primary);
	text-align: center; line-height: var(--leading-relaxed);
	margin-bottom: var(--space-4);
}
/* @handle line — kept (it's the real post owner, useful context) but as a small
   violet label rather than its own block row. Selector is class-based, not
   parent-ID-scoped, since 2026-07-22: handle/caption/metrics are now three
   independently-orderable pieces (see popup_confirmacao_de_link() in
   home.js) rather than one fixed #emoji_container wrapper, so the handle's
   position relative to its siblings varies by content type. */
#popup_servicos_home .link_preview_handle {
	display: block;
	text-align: center;
	font-size: var(--text-xs); font-weight: var(--weight-semibold);
	color: var(--color-text-brand-deep);
	margin-bottom: var(--space-4);
}
#popup_servicos_home .metricas {
	display: flex; justify-content: center; flex-wrap: wrap;
	gap: var(--space-7);
	margin-bottom: var(--space-6);
}
#popup_servicos_home .metricas span {
	display: inline-flex !important; align-items: center; gap: 4px;
	font-size: var(--text-2xs); color: var(--color-text-secondary);
}
#popup_servicos_home .metricas i { font-size: 15.6px; }
#popup_servicos_home .erro_scraper {
	display: block; text-align: center;
	font-size: var(--text-xs); font-weight: var(--weight-semibold);
	color: var(--pink-500);
	margin-bottom: var(--space-4);
}
#popup_servicos_home a.dados_da_previa {
	display: block;
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-sm);
	padding: var(--space-4) var(--space-6);
	margin-bottom: var(--space-6);
	text-align: center;
	font-size: var(--text-2xs); color: var(--color-text-brand-deep);
	text-decoration: none;
	word-break: break-all;
}
#popup_servicos_home:has(> #link_preview) #botoes {
	display: flex; flex-direction: column; gap: var(--space-4);
	margin-top: 0;
}
#popup_servicos_home:has(> #link_preview) #botoes a {
	display: block; width: 100%;
	text-align: center;
	border-radius: var(--radius-md);
	padding: var(--space-6);
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	box-shadow: none;
}
/* #confirmo (primary, "confirmar e continuar") keeps the shared CTA gradient/shadow
   from the generic #botoes a rule above; #nao_confirma here becomes the secondary
   "mudar link" action — outlined, not filled, so the two aren't equally weighted.
   Real DOM order is nao_confirma-then-confirmo; the design shows the primary
   action first, so that's flipped visually here without touching the DOM. */
#popup_servicos_home:has(> #link_preview) #botoes #confirmo { order: 1; }
#popup_servicos_home:has(> #link_preview) #botoes #nao_confirma {
	order: 2;
	background: none; color: var(--color-text-brand-deep);
	border: 1px solid var(--violet-300);
	box-shadow: none;
}

/* Shape 3 — the generic "ATENÇÃO" + message + "CHAMAR SUPORTE" popup (home.js's
   cria_popup_generico_com_mensagem_personalizada(): validation errors, link-not-
   found, private profile, wrong media type, etc). Gated on a #botoes wa.me link,
   unique to this flow (see boom.js skinGenericErrorPopup). Note: home.js's
   mensagem string is wrapped in one outer <p>, but often already contains its
   own <p> tags (e.g. the "link not found" message + link + instruction) — the
   browser auto-closes the outer <p> at the first nested one, so these end up as
   sibling <p> elements directly under the popup, which is what the ">  p" rule
   below targets. */
.ui-dialog:has(#popup_servicos_home #botoes a[href*="wa.me"]) { border-top: 4px solid #6D28D9; }
#popup_servicos_home:has(#botoes a[href*="wa.me"]) .close-btn {
	top: -1px; right: -1px;
	width: auto; height: auto;
	background: none;
	font-size: 20.8px;
}
#popup_servicos_home:has(#botoes a[href*="wa.me"]) > p {
	font-size: var(--text-xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed);
	margin: 0 0 var(--space-4);
}
#popup_servicos_home:has(#botoes a[href*="wa.me"]) > p:last-of-type { margin-bottom: 0; }
#popup_servicos_home:has(#botoes a[href*="wa.me"]) > p a {
	color: var(--color-text-brand-deep); word-break: break-all;
}
#popup_servicos_home:has(#botoes a[href*="wa.me"]) #botoes {
	display: flex; flex-direction: column; gap: var(--space-4);
	margin-top: var(--space-6);
}
#popup_servicos_home:has(#botoes a[href*="wa.me"]) #botoes a {
	display: block; width: 100%;
	text-align: center;
	border-radius: var(--radius-md);
	padding: var(--space-6);
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	box-shadow: none;
}
/* "chamar suporte" — WhatsApp-tinted so it reads as its own action, not a
   second, equally-weighted "entendi / voltar". green-800-on-green-100 (not
   white-on-#25D366) because white text on the raw WhatsApp green fails WCAG
   contrast (~2:1) — this pairing is the same one already used for the
   cart-added-popup's success icon and hits 8:1+. */
#popup_servicos_home:has(#botoes a[href*="wa.me"]) #botoes a.boom-popup-skin__btn--whatsapp {
	display: flex; align-items: center; justify-content: center; gap: var(--space-3);
	background: var(--green-100); color: var(--green-800);
}
#popup_servicos_home:has(#botoes a[href*="wa.me"]) #botoes a.boom-popup-skin__btn--whatsapp:hover {
	filter: none; background: var(--green-200); color: var(--green-800);
}

/* Loading state ("CARREGANDO INFORMAÇÕES DO LINK") shown briefly while the real
   scraper AJAX call is in flight, before #link_preview exists. */
.ui-dialog:has(#popup_servicos_home > #carregando) { border-top: 4px solid #6D28D9; }
#popup_servicos_home #carregando {
	display: flex; flex-direction: column; align-items: center;
	gap: var(--space-5);
	padding: var(--space-9) 0;
	text-align: center;
}
#popup_servicos_home #carregando i { font-size: 28.6px; color: var(--color-text-brand); }
#popup_servicos_home #carregando #texto p { margin: 0; }
#popup_servicos_home #carregando #texto p:not(.boom-cart-added-popup__title) { font-size: var(--text-xs); color: var(--color-text-secondary); }

/* "adicionado ao carrinho!" popup (boom.js initCartAddedPopup) — a plain
   theme-owned element, not a jQuery UI dialog. 3 states now (2026-07-19,
   see boom.js's own doc comment): loading (shown the instant #confirmo is
   clicked, via the 'adding_to_cart' body event) -> success ('added_to_cart')
   or error ('boom_add_to_cart_error'). Only one .boom-cart-added-popup__state
   is ever visible at a time, picked by the popup's own [data-state] — content
   swaps in place instead of closing this popup and opening a different one.
   Shares .boom-popup-backdrop with the jQuery UI popups above (see
   initPopupBackdrop's anyDialogOpen check). */
.boom-cart-added-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	background: var(--color-bg-surface);
	border-top: 4px solid #6D28D9;
	border-radius: var(--radius-xl);
	padding: var(--space-9) var(--space-8);
	box-sizing: border-box;
	box-shadow: var(--shadow-xl);
}
/* "adicionando no carrinho" (loading state) is just a spinner + one line of
   text — noticeably smaller than the success/error states' icon+title+sub(+
   buttons), so it gets its own bigger box rather than sharing the base size. */
.boom-cart-added-popup[data-state="loading"] {
	width: 90%;
	padding: var(--space-11) var(--space-9);
}
.boom-cart-added-popup.is-open { display: block; }
.boom-cart-added-popup__state {
	display: none;
	flex-direction: column; align-items: center; text-align: center; gap: var(--space-4);
}
.boom-cart-added-popup[data-state="loading"] .boom-cart-added-popup__state--loading,
.boom-cart-added-popup[data-state="success"] .boom-cart-added-popup__state--success,
.boom-cart-added-popup[data-state="error"] .boom-cart-added-popup__state--error {
	display: flex;
}
/* Same visual convention as #popup_servicos_home/#cashboom_popup's .close-btn:
   circular tinted badge, top-right corner. This popup is theme-built (not one
   of home.js's jQuery UI dialogs), so it needs its own close affordance. */
.boom-cart-added-popup__close {
	position: absolute; top: var(--space-4); right: var(--space-4);
	width: 24px; height: 24px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	border: none; padding: 0; cursor: pointer;
}
.boom-cart-added-popup__close i { font-size: 16.9px; }
/* Hidden during the (normally sub-second) loading state — there's nothing to
   cancel mid-request, and an X here just invites a tap that reads as "did it
   work?" uncertainty rather than actually doing anything useful. */
.boom-cart-added-popup[data-state="loading"] .boom-cart-added-popup__close { display: none; }
.boom-cart-added-popup__icon {
	width: 44px; height: 44px;
	border-radius: 50%;
	background: var(--green-100);
	display: flex; align-items: center; justify-content: center;
}
.boom-cart-added-popup__icon i { font-size: 28.6px; color: var(--green-700); }
/* Error state reuses --color-*-warning (amber), not a new red/danger token —
   this design system doesn't have one (see the upsell button's own green,
   not red, for the deliberate reasoning against reaching for red here) and
   amber is already the established "something needs attention" semantic
   elsewhere (e.g. .boom-status-popup__row--warning). */
.boom-cart-added-popup__icon--error { background: var(--color-bg-warning); }
.boom-cart-added-popup__icon--error i { color: var(--color-text-warning); }
/* Loading state's spinner matches the icon circle's own size/tint so the 3
   states don't visibly jump in height swapping between them — same
   brand-tinted-circle treatment as .boom-cart-added-popup__icon, not a bare
   spinner floating on its own. Motion is functional (real progress
   indicator), not decorative — tokens.css's "no decorative looping
   animation" rule is about ornamental motion, not this. */
.boom-cart-added-popup__spinner {
	width: 44px; height: 44px;
	border-radius: 50%;
	border: 3px solid var(--color-bg-surface-tint);
	border-top-color: var(--color-text-brand);
	animation: boom-spin 0.7s linear infinite;
}
@keyframes boom-spin { to { transform: rotate(360deg); } }
.boom-cart-added-popup__title { font: var(--weight-bold) var(--text-base) var(--font-body); color: var(--color-text-brand-deep); }
.boom-cart-added-popup__sub { font-size: var(--text-xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); }
.boom-cart-added-popup__btn {
	display: flex; align-items: center; justify-content: center; gap: var(--space-3);
	width: 100%; margin-top: var(--space-3);
	background: var(--color-bg-cta); color: #fff;
	border: none; border-radius: var(--radius-md);
	padding: var(--space-6); box-sizing: border-box;
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	text-align: center; text-decoration: none;
	cursor: pointer;
}
.boom-cart-added-popup__btn i { font-size: 15.6px; flex-shrink: 0; }
.boom-cart-added-popup__btn:hover { filter: brightness(1.05); color: #fff; }
/* "continuar comprando" / "ver carrinho" — secondary actions, outlined so
   they aren't equally weighted against the primary "finalizar compra" CTA. */
.boom-cart-added-popup__btn--secondary {
	background: none; color: var(--color-text-brand-deep);
	border: 1px solid var(--violet-300);
}
.boom-cart-added-popup__btn--secondary:hover { filter: none; background: var(--color-bg-surface-tint); color: var(--color-text-brand-deep); }
/* "continuar comprando" — deliberately not the plain outline the other
   secondary action gets: this is the upsell path (keep shopping), so it
   gets a real fill rather than reading as the least important button on the
   screen. History: --color-accent-pink originally (2026-07-17, read as a
   "stop"/error red) → --green-700 (2026-07-19) → var(--color-bg-cta)
   (2026-07-19, later same day, explicit user instruction) — now the same
   violet CTA gradient "finalizar compra" uses, reading as an equally real
   action rather than a muted secondary one. */
.boom-cart-added-popup__btn--upsell {
	background: var(--color-bg-cta); color: #fff;
	border: none;
}
.boom-cart-added-popup__btn--upsell:hover { filter: brightness(1.05); color: #fff; }

/* ---------- Status dos serviços / promoções da semana hub ---------- */
/* One bordered card holding both accordions, matching the mockup's tpl 248
   wrapper (Boom Home.dc.html — accordion headers separated by border-top). */
.boom-hub {
	border: var(--border-hairline);
	border-radius: var(--radius-lg);
	background: var(--color-bg-surface);
	overflow: hidden;
}

/* Generic accordion hook — JS-driven via [data-boom-accordion]/[data-open]
   (boom.js's existing DOMContentLoaded handler), CSS added here since this
   is the first section to actually use it. Visual language (chevron rotate,
   height reveal) mirrors the checkbox-driven #accordion-regras-info pattern
   already established for "ver regras do serviço". */
.boom-hub__accordion + .boom-hub__accordion { border-top: var(--border-hairline); }
.boom-hub__acc-head {
	display: flex; align-items: center; gap: var(--space-4);
	width: 100%;
	background: var(--color-bg-surface-tint);
	border: none; margin: 0;
	padding: 9px 13px;
	cursor: pointer;
	text-align: left;
	font: inherit; color: inherit;
}
.boom-hub__acc-icon {
	flex-shrink: 0;
	width: 24px; height: 24px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface);
	display: flex; align-items: center; justify-content: center;
	box-shadow: var(--shadow-xs);
}
.boom-hub__acc-icon i { font-size: 16.9px; color: var(--color-text-brand); }
.boom-hub__acc-titles { display: flex; flex-direction: column; }
.boom-hub__acc-title {
	font-size: var(--text-base); font-weight: var(--weight-black);
	color: var(--color-text-brand-deep);
	text-transform: uppercase; letter-spacing: var(--tracking-eyebrow);
}
.boom-hub__acc-title--flex { flex: 1 1 0%; }
.boom-hub__acc-sub { font-size: var(--text-2xs); color: var(--color-text-secondary); font-weight: var(--weight-medium); margin-top: 1px; }
.boom-hub__acc-head::after {
	content: "";
	flex-shrink: 0;
	margin-left: auto;
	width: 11px; height: 11px;
	background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7' fill='none'%3E%3Cpath d='M1 1L5.5 5.5L10 1' stroke='%236D28D9' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / 11px 7px;
	transition: transform var(--duration-base) var(--ease-standard);
}
.boom-hub__accordion[data-open] .boom-hub__acc-head::after { transform: rotate(180deg); }
.boom-hub__acc-body {
	max-height: 3000px; overflow: hidden; opacity: 1;
	padding: var(--space-6) 13px 14px;
	transition: max-height var(--duration-slow) var(--ease-standard), opacity var(--duration-base) var(--ease-standard), padding var(--duration-slow) var(--ease-standard);
}
.boom-hub__accordion:not([data-open]) .boom-hub__acc-body {
	max-height: 0; opacity: 0;
	padding-top: 0; padding-bottom: 0;
}

/* Status ticker: one box per message type, each cycling its rows via a
   JS-driven translateY on .boom-status-box__track (boom.js initStatusTicker,
   translateY step must match this row's height). Layout matches Boom
   Home.dc.html's own ticker markup (2026-07-25, values scaled 1.3x from
   its 46px-tall row per this project's established mockup->live factor):
   tag+date share one line (row-head, flex-start + gap - NOT space-between,
   confirmed against the mockup's actual inline styles), title below on
   its own line. Tag/title stay forced single-line (nowrap + ellipsis)
   since this fixed-height cycling can't accommodate a variable row height
   the way the popup's free-flowing list can. */
.boom-status-box {
	border-radius: var(--radius-sm);
	padding: 0 13px;
	height: 60px;
	overflow: hidden;
	position: relative;
}
.boom-status-box + .boom-status-box { margin-top: 7.8px; }
.boom-status-box--success { background: var(--color-bg-success); border: var(--border-hairline); border-color: var(--color-border-success); }
.boom-status-box--warning { background: var(--color-bg-warning); border: var(--border-hairline); border-color: var(--color-border-warning); }
.boom-status-box__track { display: flex; flex-direction: column; transition: transform 0.6s var(--ease-standard); }
.boom-status-box__row {
	height: 60px; flex-shrink: 0;
	display: flex; align-items: center; gap: 9.1px;
}
.boom-status-box__row i { font-size: 18.2px; flex-shrink: 0; }
.boom-status-box__row-body { display: flex; flex-direction: column; gap: 2.6px; min-width: 0; }
.boom-status-box__row-head { display: flex; align-items: center; gap: 7.8px; }
.boom-status-box__row-tag { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.boom-status-box__row-text { display: block; font-size: var(--text-xs); font-weight: var(--weight-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.boom-status-box__row-date { font-size: 10.4px; opacity: 0.75; flex-shrink: 0; white-space: nowrap; }
.boom-status-box--success .boom-status-box__row { color: var(--color-text-success); }
.boom-status-box--warning .boom-status-box__row { color: var(--color-text-warning); }
.boom-status-box--success .boom-status-box__row-tag { background: var(--color-bg-success-strong); color: var(--color-text-success); }
.boom-status-box--warning .boom-status-box__row-tag { background: var(--color-bg-warning-strong); color: var(--color-text-warning); }

/* Promoções da semana carousel */
.boom-promo-scroll {
	display: flex; gap: var(--space-5);
	overflow-x: auto;
	padding-bottom: 2px;
	scroll-snap-type: x proximity;
	cursor: grab;
}
.boom-promo-scroll:active { cursor: grabbing; }
.boom-promo-scroll.boom-no-scrollbar { scrollbar-width: none; -ms-overflow-style: none; }
.boom-promo-scroll.boom-no-scrollbar::-webkit-scrollbar { display: none; }
/* Popup-only additions to .boom-promo-tile (base styling shared with the
   on-page "promoções da semana" row, see that section's CSS above) — a
   clickable services checklist and a weekend foot note, styled for the
   same on-dark card background since these tiles are purple/dark here
   too, not the popup's old plain-surface .boom-promo-card look. */
.boom-promo-tile__services-label {
	font-size: 10.4px; font-weight: var(--weight-bold);
	color: rgba(255,255,255,0.85);
	margin: 11.7px 0 5.2px;
}
.boom-promo-tile__services {
	list-style: none; margin: 0; padding: 0;
	display: flex; flex-direction: column; gap: 3.9px;
}
/* align-items:flex-start (not center, 2026-07-29) - center vertically
   centers the checkmark against a wrapped 2-line service name's FULL
   height, putting it roughly between the two lines instead of level with
   the first one - reads as stray left-side space on line 1 and a misaligned
   icon overall. flex-start keeps the icon level with the first line
   regardless of how many lines the name wraps to. */
.boom-promo-tile__services li {
	display: flex; align-items: flex-start; gap: 5.2px;
	font-size: 10.4px; color: rgba(255,255,255,0.85);
}
.boom-promo-tile__services i { color: #fff; font-size: 11.7px; flex-shrink: 0; }
/* text-align:left explicit (2026-07-29) - the real cause of the "extra
   left space" reported on long, wrapping service names: <button> has a
   browser-default text-align:center, invisible on a single line (the box
   already hugs the text) but obvious once the name wraps to 2 lines and the
   flex item's rendered width ends up wider than its longest line needs -
   both lines then sit centered inside that box instead of flush left. */
.boom-promo-tile__service-link {
	background: none; border: none; padding: 0;
	font: inherit; font-size: 10.4px; font-weight: var(--weight-semibold);
	color: #fff;
	text-align: left;
	text-decoration: underline; text-underline-offset: 2px;
	cursor: pointer;
}
.boom-promo-tile__service-link:hover { color: rgba(255,255,255,0.8); }
.boom-promo-tile__foot {
	border-top: 1px solid rgba(255,255,255,0.16);
	margin-top: 11.7px; padding-top: 11.7px;
	font-size: 10.4px; color: rgba(255,255,255,0.85); text-align: center;
}
.boom-promo-dots { display: flex; justify-content: center; gap: 7.5px; margin-top: var(--space-4); }
.boom-promo-dot {
	width: 5px; height: 5px; border-radius: var(--radius-pill);
	background: var(--violet-200);
	transition: width var(--duration-base) var(--ease-standard), background var(--duration-base) var(--ease-standard);
}
.boom-promo-dot.is-active { width: 17.5px; background: var(--color-text-brand); }
.boom-promo-cta {
	display: flex; align-items: center; justify-content: center; gap: var(--space-2);
	width: 100%; margin-top: var(--space-5);
	background: none; border: none; padding: 0;
	font-family: inherit; text-decoration: none; cursor: pointer;
}
.boom-promo-cta span { font-size: var(--text-2xs); font-weight: var(--weight-bold); color: var(--color-text-brand); }
.boom-promo-cta i { font-size: 14.3px; color: var(--color-text-brand); }

/* "todas as promoções" popup — theme-owned (not a jQuery UI dialog), same
   centered-modal convention as .boom-cart-added-popup, shares the same
   .boom-popup-backdrop (see initPopupBackdrop's anyDialogOpen check). Reuses
   .boom-promo-tile/.boom-promo-tile--alt (2026-07-24: same on-page card
   style as "promoções da semana", not the old plain-surface
   .boom-promo-card) as-is; only the fixed on-page width needs overriding
   since these stack full-width instead of scrolling. */
.boom-all-promos-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	max-height: min(640px, calc(100% - 2 * var(--page-margin)));
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl);
	padding: var(--space-8);
	box-sizing: border-box;
	flex-direction: column;
	box-shadow: var(--shadow-xl);
	/* Clips __scroll's corners to match the popup's own radius - same
	   reason as .boom-cashboom-popup's own overflow:hidden. */
	overflow: hidden;
}
.boom-all-promos-popup.is-open { display: flex; }
.boom-all-promos-popup__close {
	width: 24px; height: 24px; flex-shrink: 0;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	border: none; padding: 0; cursor: pointer;
}
.boom-all-promos-popup__close i { font-size: 16.9px; }
.boom-all-promos-popup__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); flex-shrink: 0; margin-bottom: var(--space-6); }
.boom-all-promos-popup__head-left { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.boom-all-promos-popup__icon {
	width: 32px; height: 32px; flex-shrink: 0;
	border-radius: var(--radius-md);
	background: var(--color-bg-surface-tint);
	display: flex; align-items: center; justify-content: center;
}
.boom-all-promos-popup__icon i { font-size: 19.5px; color: var(--color-text-brand-deep); }
.boom-all-promos-popup__title { font: var(--font-section-title); color: var(--color-text-brand-deep); }
.boom-all-promos-popup__scroll { display: flex; flex: 1; min-height: 0; flex-direction: column; position: relative; overflow: hidden; margin-right: calc(-1 * var(--space-8)); }
.boom-all-promos-popup__list {
	display: flex; flex-direction: column; gap: var(--space-4);
}
.boom-all-promos-popup__list .boom-promo-tile { width: 100%; }
/* "tip" content — mandatory pattern (see explanation.md): the --color-*-tip
   semantic (not brand/secondary text colors) plus icon positioned a few
   pixels to the text's own left, left-aligned — not centered as a plain
   caption line. */
.boom-all-promos-popup__tip {
	display: flex; align-items: flex-start; justify-content: center; gap: 3px;
	flex-shrink: 0; margin: var(--space-5) 0 0; text-align: center;
	background: var(--color-bg-tip); border: var(--border-hairline); border-color: var(--color-border-tip);
	border-radius: var(--radius-sm);
	padding: var(--space-4) var(--space-5);
	font-size: var(--text-2xs); color: var(--color-text-tip);
}
.boom-all-promos-popup__tip i { color: var(--color-text-tip); flex-shrink: 0; }
.boom-all-promos-popup__hint {
	display: flex; align-items: center; justify-content: center; gap: var(--space-2);
	flex-shrink: 0; margin: var(--space-5) 0 0;
	font-size: var(--text-2xs); color: var(--color-text-secondary);
}
.boom-all-promos-popup__hint i { color: var(--color-text-brand); }
.boom-all-promos-popup__btn {
	flex-shrink: 0; width: 100%; margin-top: var(--space-5);
	background: var(--color-bg-cta); color: #fff;
	border: none; border-radius: var(--radius-md);
	padding: var(--space-6); box-sizing: border-box;
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	text-align: center; cursor: pointer;
}
.boom-all-promos-popup__btn:hover { filter: brightness(1.05); }

/* Auto-shown "today's promotion" popup (Boom Home.dc.html's promoPopupOpen).
   Same theme-owned/.is-open/shared-backdrop convention as the popups above;
   the violet top border is this popup's one distinguishing visual accent. */
.boom-today-promo-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl);
	border-top: 4px solid var(--color-text-brand-deep);
	padding: var(--space-9);
	box-sizing: border-box;
	box-shadow: var(--shadow-xl);
}
.boom-today-promo-popup.is-open { display: block; }
.boom-today-promo-popup__close {
	position: absolute; top: var(--space-4); right: var(--space-4);
	width: 24px; height: 24px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	border: none; padding: 0; cursor: pointer;
}
.boom-today-promo-popup__close i { font-size: 16.9px; }
.boom-today-promo-popup__eyebrow { display: flex; align-items: center; gap: var(--space-4); margin-bottom: var(--space-7); }
.boom-today-promo-popup__icon {
	width: 34px; height: 34px; flex-shrink: 0;
	border-radius: var(--radius-md);
	background: var(--color-bg-surface-tint);
	display: flex; align-items: center; justify-content: center;
}
.boom-today-promo-popup__icon i { font-size: 20.8px; color: var(--color-text-brand-deep); }
.boom-today-promo-popup__eyebrow-text {
	font: var(--font-eyebrow); color: var(--color-text-brand);
	text-transform: uppercase; letter-spacing: 0.4px;
}
.boom-today-promo-popup__title { font: var(--font-section-title); color: var(--color-text-brand-deep); margin-bottom: var(--space-3); }
.boom-today-promo-popup__weekend-note { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--color-text-brand-deep); margin: 0 0 var(--space-6); }
.boom-today-promo-popup__desc { font-size: var(--text-xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin-bottom: var(--space-2); }
.boom-today-promo-popup__example { font-size: var(--text-xs); font-weight: var(--weight-bold); color: var(--color-text-brand-deep); margin: 0 0 var(--space-6); }
.boom-today-promo-popup__services-label { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--color-text-primary); margin: 0 0 var(--space-3); }
.boom-today-promo-popup__services {
	list-style: none; margin: 0 0 var(--space-8); padding: 0;
	display: flex; flex-direction: column; gap: var(--space-2);
}
.boom-today-promo-popup__services li {
	display: flex; align-items: center; gap: var(--space-3);
	font-size: var(--text-xs); color: var(--color-text-secondary);
}
.boom-today-promo-popup__services i { color: var(--color-text-brand-deep); font-size: 14.3px; flex-shrink: 0; }
.boom-today-promo-popup__cta {
	display: block; width: 100%; margin-bottom: var(--space-4);
	background: var(--color-bg-cta); color: #fff;
	border: none; border-radius: var(--radius-md);
	padding: var(--space-6); box-sizing: border-box;
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	text-align: center; cursor: pointer;
}
.boom-today-promo-popup__cta:hover { filter: brightness(1.05); color: #fff; }
.boom-today-promo-popup__dismiss {
	display: block; width: 100%;
	background: none; border: none; padding: var(--space-3);
	font-size: var(--text-sm); font-weight: var(--weight-semibold);
	color: var(--color-text-secondary);
	text-align: center; cursor: pointer;
}

/* "compre com tranquilidade" — admin-manageable destaques (boom-core's
   destaques module). The row of circles is pure CSS + a Tabler icon glyph
   per destaque — no images/webp anywhere — so a new destaque is one admin
   post, not an asset upload. Tapping a circle opens .boom-story-overlay, a
   full-screen viewer that plays through every destaque's stories in order,
   no close in between, but stops (no looping) when the last destaque's
   last story ends (see boom.js initDestaquesViewer) with autoplay progress
   bars (4s/story, matching the Claude Design mockup's original pacing). A story
   with a YouTube video shows a static thumbnail + a tap-to-play button
   first — the real embed (and its ~500KB-1MB weight) only loads once
   actually tapped, same "lite embed" idea as the rest of this component's
   zero-image-by-default approach. */
.boom-destaques__badge {
	width: 24px; height: 24px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface-tint);
	display: inline-flex; align-items: center; justify-content: center;
	box-shadow: var(--shadow-xs);
}
.boom-destaques__badge i { font-size: 16.9px; color: var(--color-text-brand); }

@keyframes boom-pulse-icon {
	0%, 100% { transform: scale(1); opacity: 1; }
	50% { transform: scale(1.25); opacity: 0.6; }
}
.boom-destaques__watch {
	display: flex; align-items: center; gap: var(--space-3);
	margin: var(--space-4) 0 0;
	font-size: var(--text-xs); font-weight: var(--weight-black); color: var(--color-text-brand);
}
.boom-destaques__watch i { font-size: 16.9px; flex-shrink: 0; animation: boom-pulse-icon 1.3s ease-in-out infinite; }
.boom-destaque-row {
	/* margin-top here (not a ".boom-cara-nova + .boom-destaque-row" sibling
	   rule, which is what this used to be) so the row is self-sufficient
	   regardless of what precedes it -- single-product-boom.php has no
	   .boom-cara-nova badge before it, home does. */
	margin-top: var(--space-6);
	/* Fixed px per breakpoint, not a continuous viewport-scaled formula.
	   Two real-device rounds got this here: (1) real iPhone 17 vs the
	   originally-assumed width showed the assumed CSS px was too narrow
	   (~390-402 assumed, really ~403-416 -- confirmed by "4 circles fully
	   visible, some margin left" when the formula predicted a partial
	   4th); (2) once iPhone 17 looked right (88px circle, 12px gap: 3
	   whole + a clearly-cut 4th), the user asked for the SAME pattern on
	   Pro Max too, not Instagram's real behavior of just fitting one more
	   whole circle on the wider screen -- so this isn't matching
	   Instagram's per-device count difference anymore, it's matching one
	   fixed look across both. A single fixed circle/gap can't do that
	   (a wider viewport with the same slot size only ever fits more
	   items, never the same count with a same-feeling cut), so the
	   breakpoint below exists specifically to give Pro Max its own
	   bigger circle without touching iPhone 17's already-confirmed
	   values. 425px split point sits in the gap between the two
	   confirmed/estimated ranges (iPhone 17 tops out ~416, Pro Max
	   estimate starts ~440) -- the Pro Max side (100px/10px) is only
	   estimate-verified, not yet confirmed on a real Pro Max like iPhone
	   17's numbers were. See explanation.md for the full derivation. */
	display: flex; gap: 12px;
	overflow-x: auto;
	padding: var(--space-1) 0 var(--space-2) var(--space-1);
	margin-right: calc(-1 * var(--page-margin));
}
.boom-destaque-row.boom-no-scrollbar { scrollbar-width: none; -ms-overflow-style: none; }
.boom-destaque-row.boom-no-scrollbar::-webkit-scrollbar { display: none; }
.boom-destaque-circle {
	flex-shrink: 0; width: 88px;
	display: flex; flex-direction: column; align-items: center; gap: var(--space-3);
	text-align: center;
	background: none; border: none; padding: 0;
}
.boom-destaque-circle__ring {
	width: 80px; height: 80px;
	border-radius: 50%;
	padding: 4px; box-sizing: border-box;
	display: flex; box-shadow: var(--shadow-xs);
	background: linear-gradient(135deg, #F58529, #DD2A7B, #8134AF);
}
.boom-destaque-circle__inner {
	width: 100%; height: 100%; border-radius: 50%;
	background: var(--color-bg-surface);
	display: flex; align-items: center; justify-content: center;
	position: relative;
}
.boom-destaque-circle__inner > i { color: var(--color-text-brand); }
.boom-destaque-circle__play {
	position: absolute; bottom: -1px; right: -1px;
	width: 25.4px; height: 25.4px;
	border-radius: 50%;
	background: var(--color-text-brand);
	border: 2.7px solid var(--color-bg-surface);
	display: flex; align-items: center; justify-content: center;
}
.boom-destaque-circle__play i { font-size: 12px; color: var(--white); margin-left: 1px; }
@media (min-width: 425px) {
	/* Pro Max class: bigger circle so it also lands on 3 whole + a
	   clearly-cut 4th, instead of the 4-whole-plus-tiny-sliver that
	   88px/12px naturally gives on a wider screen. */
	.boom-destaque-row { gap: 10px; }
	.boom-destaque-circle { width: 100px; }
	.boom-destaque-circle__ring { width: 90.9px; height: 90.9px; }
	.boom-destaque-circle__play { width: 28.8px; height: 28.8px; }
}
.boom-destaque-circle__label {
	font-size: var(--text-2xs); font-weight: var(--weight-semibold);
	color: var(--color-text-primary); line-height: var(--leading-tight);
}
/* "Destacado" admin toggle (edit.php?post_type=boom_destaque): solid brand-fill
   variant instead of the default white/gradient-ring inner circle, same
   treatment as the desktop mockup's idx===0 "como comprar" story
   (Boom Home Desktop.dc.html ~L4233-4239). Ring gradient + play badge stay
   the same as the default style, only the inner fill/icon/label change. */
.boom-destaque-circle--destacado .boom-destaque-circle__inner { background: var(--color-text-brand); }
.boom-destaque-circle--destacado .boom-destaque-circle__inner > i { color: var(--white); }
.boom-destaque-circle--destacado .boom-destaque-circle__label { font-weight: var(--weight-black); }
.boom-destaque-dots { display: flex; justify-content: center; gap: 7.5px; margin-top: var(--space-4); }
.boom-destaque-dot {
	width: 5px; height: 5px; border-radius: var(--radius-pill);
	background: var(--violet-200);
	transition: width var(--duration-base) var(--ease-standard), background var(--duration-base) var(--ease-standard);
}
.boom-destaque-dot.is-active { width: 17.5px; background: var(--color-text-brand); }

/* Full-screen story viewer. Fixed, not a centered card like the other
   popups above — it covers the whole viewport itself, so it doesn't need
   .boom-popup-backdrop (initPopupBackdrop's shared dimmer is for popups that
   only cover part of the screen). */
.boom-story-overlay {
	display: none;
	position: fixed; z-index: 130;
	top: 0; left: 50%; transform: translateX(-50%);
	width: 100%; max-width: 448px;
	height: 100dvh;
	background: #000;
	overflow: hidden;
}
.boom-story-overlay.is-open { display: block; }
.boom-story-overlay__stage { position: relative; width: 100%; height: 100%; }
.boom-story-overlay__bg { position: absolute; inset: 0; }
.boom-story-overlay__content {
	position: absolute; inset: 0;
	display: flex; align-items: center; justify-content: center;
	padding: var(--space-10);
	pointer-events: none;
}
.boom-story-overlay__content > i { font-size: 83.2px; color: rgba(255, 255, 255, 0.92); }
.boom-story-overlay__zone { position: absolute; top: 0; bottom: 0; background: transparent; border: none; padding: 0; z-index: 1; }
.boom-story-overlay__zone--prev { left: 0; width: 35%; }
.boom-story-overlay__zone--next { right: 0; width: 65%; }
.boom-story-overlay__bars {
	position: absolute; top: 0; left: 0; right: 0;
	display: flex; gap: var(--space-2);
	padding: var(--space-5) var(--space-5) 0;
	z-index: 2;
}
.boom-story-overlay__bar { flex: 1; height: 3px; border-radius: 2px; background: rgba(255, 255, 255, 0.35); overflow: hidden; }
.boom-story-overlay__bar-fill { height: 100%; background: #fff; }
.boom-story-overlay__close {
	position: absolute; top: var(--space-5); right: var(--space-3);
	width: 38px; height: 38px; border-radius: 50%;
	background: rgba(0, 0, 0, 0.35); border: none; color: #fff;
	display: flex; align-items: center; justify-content: center;
	z-index: 2;
}
.boom-story-overlay__close i { font-size: 18.2px; }

/* Two header slots — see the front-page.php comment above this markup for
   why there are two copies of .boom-story-overlay__header instead of one
   node moved by JS. Only one is ever visible, per layout (below). */
.boom-story-overlay__top {
	position: absolute; left: 0; right: 0; top: 52px; z-index: 2;
	padding: 0 var(--space-8);
	pointer-events: none;
}
.boom-story-overlay__top .boom-story-overlay__header { display: none; color: #fff; }
.boom-story-overlay__foot {
	position: absolute; bottom: 0; left: 0; right: 0; z-index: 2;
	padding: var(--space-9) var(--space-8);
	background: linear-gradient(to top, rgba(0, 0, 0, 0.65), transparent);
	color: #fff;
	pointer-events: none;
}
.boom-story-overlay__header {
	font: var(--weight-bold) var(--story-header-size, var(--text-xl)) var(--font-display);
	margin: 0;
}
.boom-story-overlay__header:empty { display: none; }
.boom-story-overlay__texts { margin-top: var(--space-3); }
.boom-story-overlay__text {
	font-size: var(--story-text-size, var(--text-sm)); color: rgba(255, 255, 255, 0.9);
	line-height: var(--leading-relaxed);
	margin: 0 0 var(--space-2);
}
.boom-story-overlay__text:last-child { margin-bottom: 0; }
.boom-story-overlay__footer {
	display: inline-flex; margin-top: var(--space-4);
	font-size: var(--text-2xs); font-weight: var(--weight-bold);
	text-transform: uppercase; letter-spacing: var(--tracking-eyebrow);
	color: #fff; background: rgba(255, 255, 255, 0.18);
	padding: var(--space-2) var(--space-5); border-radius: var(--radius-pill);
}
.boom-story-overlay__footer:empty { display: none; }

/* ---------- Layout presets (curated, not free-form — see explanation.md's
   Pass 2 notes on why) ---------- */
/* The icon is always flex-centered at true 50% (not layout-dependent) —
   nudge it up and drop the text block below true center so "center" layout
   doesn't collide the two on top of each other. */
.boom-story-overlay__stage[data-boom-story-layout="center"] .boom-story-overlay__content { padding-bottom: 18%; }
.boom-story-overlay__stage[data-boom-story-layout="center"] .boom-story-overlay__foot {
	top: 64%; bottom: auto; transform: translateY(-50%);
	background: none; text-align: center;
}
.boom-story-overlay__stage[data-boom-story-layout="center"] .boom-story-overlay__footer { margin-left: auto; margin-right: auto; }
.boom-story-overlay__stage[data-boom-story-layout="split"] .boom-story-overlay__top .boom-story-overlay__header { display: block; }
.boom-story-overlay__stage[data-boom-story-layout="split"] .boom-story-overlay__foot .boom-story-overlay__header { display: none; }

/* ---------- Text size scale ---------- */
.boom-story-overlay__stage[data-boom-story-size="sm"] { --story-header-size: var(--text-lg); --story-text-size: var(--text-2xs); }
.boom-story-overlay__stage[data-boom-story-size="md"] { --story-header-size: var(--text-xl); --story-text-size: var(--text-sm); }
.boom-story-overlay__stage[data-boom-story-size="lg"] { --story-header-size: var(--text-2xl); --story-text-size: var(--text-base); }

/* ---------- Style patterns ----------
   All pure CSS/gradients built from --story-color (set inline by boom.js
   per story) — no images. "halo" deliberately echoes the ring around the
   destaque circle that opened this story, tying the full-screen view back
   to the small avatar that was tapped. Mirrored at a small scale in
   boom-core's destaques-admin.css for the live preview — keep both in sync
   if these change. */
.boom-story-overlay__stage[data-boom-story-pattern="aurora"] .boom-story-overlay__bg {
	background: linear-gradient(155deg, var(--story-color), #241f38);
	opacity: 0.92;
}
.boom-story-overlay__stage[data-boom-story-pattern="duotone"] .boom-story-overlay__bg {
	background: linear-gradient(180deg, var(--story-color) 0%, var(--story-color) 46%, #14101f 46%, #14101f 100%);
}
.boom-story-overlay__stage[data-boom-story-pattern="duotone"] .boom-story-overlay__content > i { font-size: 109.2px; }
.boom-story-overlay__stage[data-boom-story-pattern="spotlight"] .boom-story-overlay__bg { background: #0f0b1a; }
.boom-story-overlay__stage[data-boom-story-pattern="spotlight"] .boom-story-overlay__bg::after {
	content: ''; position: absolute; inset: 0;
	background: radial-gradient(circle at 50% 42%, var(--story-color) 0%, transparent 60%);
	opacity: 0.55;
}
.boom-story-overlay__stage[data-boom-story-pattern="spotlight"] .boom-story-overlay__content > i { font-size: 62.4px; }
.boom-story-overlay__stage[data-boom-story-pattern="halo"] .boom-story-overlay__bg { background: linear-gradient(180deg, #1a1530, #0f0b1a); }
.boom-story-overlay__stage[data-boom-story-pattern="halo"] .boom-story-overlay__content::before {
	content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 120px; height: 120px; border-radius: 50%;
	box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.25), 0 0 0 14px transparent, 0 0 0 15px rgba(255, 255, 255, 0.12), 0 0 0 30px transparent, 0 0 0 31px rgba(255, 255, 255, 0.06);
	pointer-events: none;
}

/* ---------- Custom-HTML stories ----------
   A story can bypass the header/texts/footer/pattern system entirely and
   supply its own full-slide markup (see _boom_story_custom_html on the
   PHP side) -- used for the ported Claude Design mockup slides. That
   markup owns its own header/footer look, so the generic chrome is
   hidden and __content goes full-bleed instead of icon-centered. */
.boom-story-overlay__stage.is-custom-story .boom-story-overlay__top,
.boom-story-overlay__stage.is-custom-story .boom-story-overlay__foot {
	display: none;
}
.boom-story-overlay__stage.is-custom-story .boom-story-overlay__content {
	display: block;
	padding: 0;
	overflow-y: auto;
}

/* ---------- Custom-story shared components ----------
   Reusable building blocks composed by each _boom_story_custom_html slide
   (the ported Claude Design "destaques" mockups) -- namespaced so they never
   leak outside .is-custom-story stories. No inline style="" is ever used in
   the stored HTML on purpose: it keeps everything safe under wp_kses_post()
   (which strips most inline style properties) and keeps every visual
   variant auditable here instead of scattered across 10 postmeta blobs. */
.boom-story-custom {
	position: relative;
	box-sizing: border-box;
	width: 100%;
	min-height: 100%;
	padding: 56px var(--space-8) var(--space-9);
	display: flex;
	flex-direction: column;
	overflow: hidden;
}
.boom-story-custom--dark {
	background:
		radial-gradient(ellipse 140% 60% at 70% -10%, rgba(138, 99, 232, 0.35), transparent 60%),
		linear-gradient(135deg, var(--violet-900), var(--violet-900-soft));
	color: var(--white);
}
.boom-story-custom--light {
	background:
		radial-gradient(ellipse 120% 60% at 100% -10%, rgba(255, 255, 255, 0.9), transparent 55%),
		linear-gradient(160deg, var(--cream-50), var(--cream-100));
	color: var(--ink-900);
}
.boom-story-custom__blob { position: absolute; z-index: 0; border-radius: 50%; pointer-events: none; filter: blur(30px); }
.boom-story-custom--dark .boom-story-custom__blob { background: rgba(255, 255, 255, 0.06); }
.boom-story-custom--light .boom-story-custom__blob { background: var(--violet-50); }
.boom-story-custom__blob--a { top: -110px; right: -110px; width: 260px; height: 260px; }
.boom-story-custom__blob--b { bottom: -130px; left: -90px; width: 220px; height: 220px; }
.boom-story-custom__blob--c { top: -50px; left: 30px; width: 130px; height: 130px; }
.boom-story-custom__blob--d { bottom: -50px; right: 50px; width: 150px; height: 150px; }
.boom-story-custom__watermark {
	position: absolute; z-index: 0; pointer-events: none; user-select: none;
	bottom: -8px; right: -14px; transform: rotate(-6deg);
	font-family: var(--font-display); font-weight: var(--weight-bold);
	font-size: 130px; letter-spacing: -3px; white-space: nowrap;
}
.boom-story-custom--dark .boom-story-custom__watermark { color: rgba(255, 255, 255, 0.05); }
.boom-story-custom--light .boom-story-custom__watermark { color: rgba(31, 27, 46, 0.045); }

.boom-story-custom__header {
	position: relative; z-index: 1;
	display: flex; align-items: center; justify-content: space-between; gap: var(--space-8);
	margin-bottom: var(--space-11);
}
.boom-story-custom__eyebrow {
	font: var(--weight-black) var(--text-sm) var(--font-body);
	text-transform: uppercase; letter-spacing: var(--tracking-eyebrow);
}
.boom-story-custom--dark .boom-story-custom__eyebrow { color: var(--violet-300); }
.boom-story-custom--light .boom-story-custom__eyebrow { color: var(--violet-600); }
.boom-story-custom__tile {
	flex-shrink: 0; width: 44px; height: 44px; border-radius: var(--radius-lg);
	display: flex; align-items: center; justify-content: center;
}
.boom-story-custom__tile i { font-size: 22px; }
.boom-story-custom--dark .boom-story-custom__tile { background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.14); color: var(--white); }
.boom-story-custom--light .boom-story-custom__tile { background: var(--white); border: var(--border-default); color: var(--violet-600); box-shadow: var(--shadow-xs); }

.boom-story-custom__body { position: relative; z-index: 1; flex: 1; min-height: 0; display: flex; flex-direction: column; justify-content: flex-start; gap: var(--space-9); }

.boom-story-custom__badge {
	align-self: flex-start;
	display: inline-flex; align-items: center; gap: var(--space-3);
	font: var(--weight-bold) var(--text-xs) var(--font-body);
	text-transform: uppercase; letter-spacing: var(--tracking-eyebrow);
	padding: var(--space-3) var(--space-8); border-radius: var(--radius-pill);
}
.boom-story-custom--dark .boom-story-custom__badge--hot { background: rgba(245, 158, 11, 0.2); color: #fcd34d; }
.boom-story-custom--dark .boom-story-custom__badge--success { background: rgba(74, 222, 128, 0.18); color: #86efac; }
.boom-story-custom--dark .boom-story-custom__badge--soon { background: rgba(255, 255, 255, 0.12); color: var(--violet-300); }
.boom-story-custom--light .boom-story-custom__badge--hot { background: var(--amber-50); color: var(--amber-700); }
.boom-story-custom--light .boom-story-custom__badge--success { background: var(--green-100); color: var(--green-700); }
.boom-story-custom--light .boom-story-custom__badge--soon { background: var(--violet-50); color: var(--violet-600); }

.boom-story-custom__title { margin: 0; font-family: var(--font-display); font-weight: var(--weight-bold); font-size: clamp(1.6rem, 7.5vw, 2.1rem); line-height: 1.15; overflow-wrap: break-word; }
.boom-story-custom__title--sm { font-size: clamp(1.3rem, 6vw, 1.6rem); }
.boom-story-custom__desc { margin: 0; font-family: var(--font-body); font-size: var(--text-md); line-height: var(--leading-relaxed); overflow-wrap: break-word; }
.boom-story-custom--dark .boom-story-custom__desc { color: var(--violet-300); }
.boom-story-custom--light .boom-story-custom__desc { color: var(--ink-600); }

.boom-story-custom__mt-sm { margin-top: var(--space-6); }
.boom-story-custom__mt-md { margin-top: var(--space-9); }

.boom-story-custom__stack { display: flex; flex-direction: column; gap: var(--space-7); }
.boom-story-custom__row { display: flex; align-items: center; gap: var(--space-7); border-radius: var(--radius-lg); padding: var(--space-8); }
.boom-story-custom__row--solid { background: var(--white); box-shadow: var(--shadow-lg); }
.boom-story-custom__row--soft { background: rgba(255, 255, 255, 0.08); }
.boom-story-custom__row--tint { background: var(--cream-100); }
.boom-story-custom__row--tint-violet { background: var(--violet-50); }
.boom-story-custom__row-icon { flex-shrink: 0; width: 40px; height: 40px; border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; }
.boom-story-custom__row-icon i { font-size: 19px; }
.boom-story-custom__row--solid .boom-story-custom__row-icon { background: var(--violet-50); color: var(--violet-600); }
.boom-story-custom__row--soft .boom-story-custom__row-icon { background: rgba(255, 255, 255, 0.12); color: var(--white); }
.boom-story-custom__row--tint .boom-story-custom__row-icon,
.boom-story-custom__row--tint-violet .boom-story-custom__row-icon { background: var(--white); color: var(--violet-600); }
.boom-story-custom__row-title, .boom-story-custom__row-text { flex: 1; min-width: 0; overflow-wrap: break-word; }
.boom-story-custom__row-text { display: flex; flex-direction: column; gap: 2px; }
.boom-story-custom__row-title { font: var(--weight-bold) var(--text-base) var(--font-body); }
.boom-story-custom__row-sub { font: var(--weight-medium) var(--text-xs) var(--font-body); color: var(--ink-600); overflow-wrap: break-word; }
.boom-story-custom__row--solid .boom-story-custom__row-title,
.boom-story-custom__row--tint .boom-story-custom__row-title,
.boom-story-custom__row--tint-violet .boom-story-custom__row-title { color: var(--ink-900); }
.boom-story-custom__row--soft .boom-story-custom__row-title { color: var(--white); font-weight: var(--weight-semibold); }
.boom-story-custom__row--solid .boom-story-custom__row-sub { color: var(--violet-600); }
.boom-story-custom__row--soft .boom-story-custom__row-sub { color: var(--violet-300); }

.boom-story-custom__card { background: var(--white); border-radius: var(--radius-xl); padding: var(--space-10); box-shadow: var(--shadow-lg); color: var(--ink-900); }
.boom-story-custom__card--tight { padding: var(--space-7) var(--space-4); }
.boom-story-custom__card--tight .boom-story-custom__stat-value { font-size: var(--text-xl); }
.boom-story-custom__card-grid { display: flex; gap: var(--space-8); }
.boom-story-custom__card-grid .boom-story-custom__card { flex: 1; min-width: 0; }
.boom-story-custom__card-head { display: flex; flex-direction: column; align-items: center; gap: var(--space-4); text-align: center; }
.boom-story-custom__card-head-icon { width: 40px; height: 40px; border-radius: var(--radius-md); background: var(--violet-50); color: var(--violet-600); display: flex; align-items: center; justify-content: center; }
.boom-story-custom__card-head-icon i { font-size: 19px; }
.boom-story-custom__card-head-title { font: var(--weight-bold) var(--text-base) var(--font-body); color: var(--ink-900); overflow-wrap: break-word; }

.boom-story-custom__stat { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); text-align: center; }
.boom-story-custom__stat-value { font: var(--weight-bold) var(--text-2xl) var(--font-display); color: var(--ink-900); overflow-wrap: break-word; }
.boom-story-custom__stat-value--brand { color: var(--violet-600); }
.boom-story-custom__stat-label { font: var(--weight-medium) var(--text-xs) var(--font-body); color: var(--ink-600); }

.boom-story-custom__ministeps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; }
.boom-story-custom__ministep { position: relative; display: flex; flex-direction: column; align-items: center; gap: var(--space-3); }
.boom-story-custom__ministep:not(:first-child)::before {
	content: ''; position: absolute; top: 17px; right: 50%; width: 100%; height: 2px;
	background: rgba(109, 40, 217, 0.16); z-index: 0;
}
.boom-story-custom__ministep-dot {
	position: relative; z-index: 1; width: 34px; height: 34px; border-radius: 50%;
	display: flex; align-items: center; justify-content: center;
	font: var(--weight-bold) var(--text-sm) var(--font-body);
	background: var(--cream-100); color: var(--ink-600);
}
.boom-story-custom__ministep--active .boom-story-custom__ministep-dot { background: var(--white); border: 2px solid var(--violet-600); color: var(--violet-700); }
.boom-story-custom__ministep-label { font: var(--weight-medium) var(--text-2xs) var(--font-body); color: var(--ink-600); }
.boom-story-custom__ministep--active .boom-story-custom__ministep-label { color: var(--violet-700); font-weight: var(--weight-bold); }

.boom-story-custom__steps { display: flex; flex-direction: column; }
.boom-story-custom__step { display: flex; align-items: center; gap: var(--space-7); padding: var(--space-6) 0; }
.boom-story-custom__step-dot { flex-shrink: 0; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font: var(--weight-bold) var(--text-sm) var(--font-body); }
.boom-story-custom__step-dot--done { background: var(--green-700); color: var(--white); }
.boom-story-custom__step-dot--done i, .boom-story-custom__step-dot--pending i { font-size: 15px; }
.boom-story-custom__step-dot--pending { background: var(--green-100); color: var(--green-700); }
.boom-story-custom__step-dot--num { background: var(--violet-600); color: var(--white); }
.boom-story-custom__step-line { width: 2px; height: 18px; background: var(--color-border-subtle); margin-left: 15px; }
.boom-story-custom--dark .boom-story-custom__step-line { background: rgba(255, 255, 255, 0.16); }
.boom-story-custom__step-label { flex: 1; min-width: 0; font: var(--weight-bold) var(--text-base) var(--font-body); color: var(--ink-900); overflow-wrap: break-word; }
.boom-story-custom__step-time { font: var(--weight-medium) var(--text-xs) var(--font-body); color: var(--ink-500); }

.boom-story-custom__pay-list { display: flex; flex-wrap: wrap; gap: var(--space-6); justify-content: center; }
.boom-story-custom__pay-chip { display: inline-flex; align-items: center; gap: var(--space-4); font: var(--weight-bold) var(--text-sm) var(--font-body); padding: var(--space-6) var(--space-8); border-radius: var(--radius-md); }
.boom-story-custom--dark .boom-story-custom__pay-chip { background: rgba(255, 255, 255, 0.08); color: var(--white); }
.boom-story-custom--light .boom-story-custom__pay-chip { background: var(--cream-100); color: var(--ink-900); }
.boom-story-custom__pay-chip i { font-size: 17px; }

.boom-story-custom__cta {
	align-self: flex-start; display: inline-flex; align-items: center; justify-content: center; gap: var(--space-6);
	font: var(--weight-bold) var(--text-base) var(--font-body); color: var(--white);
	padding: var(--space-8) var(--space-11); border-radius: var(--radius-pill);
	background: var(--color-bg-cta); box-shadow: var(--shadow-button);
}
.boom-story-custom__cta--block { align-self: stretch; width: 100%; box-sizing: border-box; }

.boom-story-custom__social-list { display: flex; gap: var(--space-7); }
.boom-story-custom__social-chip { width: 40px; height: 40px; border-radius: var(--radius-md); background: rgba(255, 255, 255, 0.08); color: var(--white); display: flex; align-items: center; justify-content: center; }
.boom-story-custom__social-chip i { font-size: 18px; }

.boom-story-custom__trust-grid { display: flex; gap: var(--space-6); }
.boom-story-custom__trust-item {
	flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: var(--space-3);
	border-radius: var(--radius-lg); padding: var(--space-8) var(--space-4); text-align: center;
	font: var(--weight-bold) var(--text-xs) var(--font-body);
}
.boom-story-custom--dark .boom-story-custom__trust-item { background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(255, 255, 255, 0.1); color: var(--white); }
.boom-story-custom__trust-item i { font-size: 20px; }

.boom-story-custom__footer { position: relative; z-index: 1; margin-top: var(--space-11); display: flex; flex-direction: column; gap: 4px; }
.boom-story-custom__footer-brand { font: var(--weight-bold) var(--text-lg) var(--font-display); }
.boom-story-custom__footer-url { font: var(--weight-medium) var(--text-2xs) var(--font-body); }
.boom-story-custom--dark .boom-story-custom__footer-brand,
.boom-story-custom--dark .boom-story-custom__footer-url { color: var(--white); }
.boom-story-custom--dark .boom-story-custom__footer-url { color: var(--violet-300); }
.boom-story-custom--light .boom-story-custom__footer-brand { color: var(--ink-900); }
.boom-story-custom--light .boom-story-custom__footer-url { color: var(--ink-600); }

/* YouTube slide: thumbnail + tap-to-play button. Given a higher z-index than
   .boom-story-overlay__zone and re-enabled pointer-events (its container,
   .boom-story-overlay__content, sets pointer-events:none so plain icon
   slides don't block the prev/next tap zones underneath) so the play button
   itself stays reachable above them. */
.boom-story-overlay__yt {
	position: relative; z-index: 2; pointer-events: auto;
	display: block; width: 100%; height: 100%;
	background: none; border: none; padding: 0; cursor: pointer;
}
.boom-story-overlay__yt img { width: 100%; height: 100%; object-fit: cover; }
.boom-story-overlay__yt-play {
	position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 56px; height: 56px; border-radius: 50%;
	background: rgba(0, 0, 0, 0.5);
	display: flex; align-items: center; justify-content: center;
	color: #fff;
}
.boom-story-overlay__yt-play i { font-size: 28.6px; }
.boom-story-overlay__content iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: none; }

/* "quem confia na boom" — real approved avaliações (boom-core's avaliacoes
   module). Stat tiles + a horizontal card carousel, same
   .boom-no-scrollbar/drag-to-scroll/dot-pagination technique as the promo
   carousel above (see boom.js initReviewCarousel). */
/* Boxed title row (Boom Home.dc.html ~L369-374): the badge+label pair now sits on
   its own tinted pill instead of bare on the section background. The badge itself
   switches to a plain white circle so it still reads as a distinct layer on top of
   the new tinted pill, instead of blending into it. */
/* .boom-section-head's base rule is a row (title + a "ver todos"-style action
   on the same line, see the bestseller/promo/status headers) — wrong axis for
   this one, whose second child is .boom-section-sub, not an action button. Row
   + space-between squeezed the title pill down to share the row with the sub
   text, wrapping "quem confia na boom" across 3 lines. Stack instead so the
   pill sits on its own line at its natural width, sub below it. */
.boom-confia .boom-section-head {
	flex-direction: column;
	align-items: flex-start;
}
.boom-confia .boom-section-title {
	width: 100%;
	box-sizing: border-box;
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-md);
	padding: 9px 13px;
}
.boom-confia__badge {
	width: 24px; height: 24px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface);
	display: inline-flex; align-items: center; justify-content: center;
	box-shadow: var(--shadow-xs);
}
.boom-confia__badge i { font-size: 16.9px; color: var(--color-text-brand); }
.boom-confia-stats {
	display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4);
	margin-bottom: var(--space-6);
}
.boom-confia-stat {
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	border-radius: var(--radius-md);
	padding: var(--space-6) var(--space-2);
	text-align: center;
}
.boom-confia-stat__value {
	font: var(--weight-bold) var(--text-base) var(--font-display);
	color: var(--color-text-primary);
	margin: 0;
	display: flex; align-items: center; justify-content: center; gap: var(--space-1);
}
.boom-confia-stat__value i { font-size: 14.3px; color: var(--amber-700); }
.boom-confia-stat__label { font-size: var(--text-2xs); color: var(--color-text-secondary); margin: var(--space-1) 0 0; }

.boom-confia-scroll {
	display: flex; gap: var(--space-5);
	overflow-x: auto;
	scroll-snap-type: x proximity;
	cursor: grab;
	padding-bottom: 2px;
}
.boom-confia-scroll:active { cursor: grabbing; }
.boom-confia-scroll.boom-no-scrollbar { scrollbar-width: none; -ms-overflow-style: none; }
.boom-confia-scroll.boom-no-scrollbar::-webkit-scrollbar { display: none; }
.boom-review-card {
	flex-shrink: 0; width: 196px;
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	border-radius: var(--radius-md);
	padding: var(--space-6);
	scroll-snap-align: start;
}
.boom-review-card__stars { display: flex; margin-bottom: var(--space-3); }
.boom-review-card__stars i { font-size: 11.7px; margin-right: 1px; }
.boom-review-card__text { font-size: var(--text-2xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0; }

.boom-review-cta-card {
	flex-shrink: 0; width: 150px;
	background: var(--color-bg-surface-tint);
	border: 1px dashed var(--violet-300);
	border-radius: var(--radius-md);
	padding: var(--space-6);
	scroll-snap-align: start;
	display: flex; flex-direction: column; align-items: center; justify-content: center;
	text-align: center; gap: var(--space-3);
	cursor: pointer;
	font-family: inherit;
}
.boom-review-cta-card__icon {
	width: 30px; height: 30px;
	border-radius: 50%;
	background: var(--color-bg-surface);
	display: flex; align-items: center; justify-content: center;
}
.boom-review-cta-card__icon i { font-size: 19.5px; color: var(--color-text-brand); }
.boom-review-cta-card__title { font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--color-text-brand-deep); line-height: var(--leading-normal); }
.boom-review-cta-card__hint { font-size: var(--text-2xs); color: var(--color-text-secondary); font-weight: var(--weight-semibold); }

.boom-review-dots { display: flex; justify-content: center; gap: 7.5px; margin-top: var(--space-4); }
.boom-review-dot {
	width: 5px; height: 5px; border-radius: var(--radius-pill);
	background: var(--violet-200);
	transition: width var(--duration-base) var(--ease-standard), background var(--duration-base) var(--ease-standard);
}
.boom-review-dot.is-active { width: 17.5px; background: var(--color-text-brand); }

/* Review-submission modal — theme-owned, same centered-modal/.is-open/
   shared-backdrop convention as .boom-today-promo-popup (violet top-border
   accent reused verbatim). Shares .boom-popup-backdrop via initPopupBackdrop's
   anyDialogOpen() check (see boom.js). No identity field is ever rendered
   here (no name/city/state) — see avaliacoes-loader.php. */
.boom-avaliacao-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	max-height: min(600px, calc(100% - 2 * var(--page-margin)));
	overflow-y: auto;
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl);
	border-top: 4px solid var(--color-text-brand-deep);
	padding: var(--space-8);
	box-sizing: border-box;
	box-shadow: var(--shadow-xl);
}
.boom-avaliacao-popup.is-open { display: block; }
.boom-avaliacao-popup__close {
	position: absolute; top: var(--space-4); right: var(--space-4);
	width: 24px; height: 24px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	border: none; padding: 0; cursor: pointer;
}
.boom-avaliacao-popup__close i { font-size: 16.9px; }
.boom-avaliacao-popup__head { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-2); padding-right: var(--space-9); }
.boom-avaliacao-popup__head i { font-size: 22.1px; color: var(--color-text-brand-deep); }
.boom-avaliacao-popup__title { font: var(--weight-bold) var(--text-md) var(--font-body); color: var(--color-text-brand-deep); margin: 0; }
.boom-avaliacao-popup__sub { font-size: var(--text-xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0 0 var(--space-7); }
.boom-avaliacao-popup__label { font-size: var(--text-xs); font-weight: var(--weight-medium); color: var(--color-text-secondary); margin: 0 0 var(--space-3); }
.boom-avaliacao-popup__stars { display: flex; gap: var(--space-3); margin-bottom: var(--space-7); }
.boom-avaliacao-popup__star {
	background: none; border: none; padding: 0; cursor: pointer;
	line-height: 1;
}
.boom-avaliacao-popup__star i { font-size: 28.6px; color: var(--violet-200); }
.boom-avaliacao-popup__star.is-active i { color: var(--amber-700); }
.boom-avaliacao-popup__textarea {
	width: 100%; box-sizing: border-box;
	background: var(--color-bg-surface-violet-50);
	border: none; border-radius: var(--radius-sm);
	padding: var(--space-5) var(--space-6);
	font-size: var(--text-sm); font-family: inherit;
	resize: none;
	margin-bottom: var(--space-7);
}
.boom-avaliacao-popup__error {
	font-size: var(--text-2xs); color: var(--color-text-warning);
	margin: calc(var(--space-7) * -1) 0 var(--space-6);
}
.boom-avaliacao-popup__submit {
	display: block; width: 100%;
	background: var(--color-bg-cta); color: #fff;
	border: none; border-radius: var(--radius-md);
	padding: var(--space-6); box-sizing: border-box;
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	text-align: center; cursor: pointer;
}
.boom-avaliacao-popup__submit:hover { filter: brightness(1.05); color: #fff; }
.boom-avaliacao-popup__submit:disabled { opacity: 0.6; cursor: default; }
/* [hidden] and this class share specificity (0,1,0 each); the UA [hidden]
   rule loses to whichever author rule comes later in the cascade, so an
   explicit [hidden] override is needed or boom.js's hidden-attribute toggle
   between the pending/success views would show both at once. */
.boom-avaliacao-popup__pending[hidden],
.boom-avaliacao-popup__success[hidden] { display: none; }
.boom-avaliacao-popup__success {
	display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-4);
	padding: var(--space-5) 0 var(--space-2);
}
.boom-avaliacao-popup__success-icon {
	width: 40px; height: 40px;
	border-radius: 50%;
	background: var(--green-100);
	display: flex; align-items: center; justify-content: center;
}
.boom-avaliacao-popup__success-icon i { font-size: 26px; color: var(--green-700); }
.boom-avaliacao-popup__success-title { font: var(--weight-bold) var(--text-base) var(--font-body); color: var(--color-text-primary); margin: 0; }
.boom-avaliacao-popup__success-sub { font-size: var(--text-xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0; }
.boom-avaliacao-popup__success .boom-avaliacao-popup__submit { margin-top: var(--space-2); }


/* "boom assinatura" card popup (Boom Home.dc.html:676-717 content, moved off
   the page into a popup opened by the cards grid). .boom-assinatura__card
   keeps its dark treatment — fixed-dark surface using the mockup's own
   literal hex values, same convention as .boom-combobox__panel's gradient
   comment — not --color-bg-hero (a different, lighter violet gradient used
   for the hero section) and not a new token, since nothing else in the
   design system uses this exact pair. */
/* Wider than the other card popups (320px) — this is the only one with a
   real multi-field form nested inside it, including the country-picker
   dropdown (.boom-phone-input__panel), which needs more breathing room than
   a plain read-only popup does. 360px is still comfortably inside a single
   mobile-first column at the project's --page-margin gutters. */
.boom-assinatura-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	max-height: min(680px, calc(100% - 2 * var(--page-margin)));
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-xl);
	overflow-y: auto;
}
.boom-assinatura-popup.is-open { display: block; }
.boom-assinatura-popup .boom-assinatura__card { margin: 0; }
.boom-assinatura-popup__close {
	position: absolute; top: var(--space-4); right: var(--space-4);
	width: 24px; height: 24px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: rgba(255, 255, 255, 0.1);
	color: #fff;
	border: none; padding: 0; cursor: pointer;
	z-index: 1;
}
.boom-assinatura-popup__close i { font-size: 14px; }

.boom-assinatura__card {
	background: linear-gradient(155deg, #241F38, #1F1B2E);
	border-radius: var(--radius-lg);
	padding: var(--space-7);
	position: relative;
}
.boom-assinatura__pill {
	display: inline-block;
	background: var(--color-text-brand);
	color: #fff;
	font-size: 9.75px; font-weight: var(--weight-bold);
	padding: 3px 8px;
	border-radius: var(--radius-pill);
	letter-spacing: 0.5px;
}
.boom-assinatura__title {
	font: var(--weight-bold) var(--text-base) var(--font-display);
	color: #fff;
	margin: var(--space-3) 0 0;
}
.boom-assinatura__subtitle { font-size: var(--text-2xs); color: #C4B5FD; margin: var(--space-2) 0 0; }
.boom-assinatura__copy { font-size: var(--text-xs); color: #DDD6FE; line-height: var(--leading-relaxed); margin: var(--space-3) 0 0; }

.boom-assinatura__open {
	background: rgba(255, 255, 255, 0.06);
	border-radius: var(--radius-md);
	padding: var(--space-5);
	margin-top: var(--space-6);
}
.boom-assinatura__form-label { font-size: var(--text-2xs); color: #fff; font-weight: var(--weight-semibold); margin: 0 0 var(--space-4); }
.boom-assinatura__input {
	display: block;
	width: 100%; box-sizing: border-box;
	background: var(--color-bg-surface);
	border: 2px solid transparent;
	border-radius: var(--radius-sm);
	padding: var(--space-4) var(--space-5);
	font-size: var(--text-2xs); font-family: inherit;
	margin-bottom: var(--space-4);
}
.boom-assinatura__input.is-invalid { border-color: #FCA5A5; }
.boom-assinatura__error {
	font-size: 9.75px; color: #FCA5A5;
	margin: 0 0 var(--space-4);
	text-align: center;
}
.boom-assinatura__submit {
	display: block; width: 100%;
	background: var(--color-text-brand);
	color: #fff;
	border: none; border-radius: var(--radius-sm);
	padding: var(--space-5);
	font-size: var(--text-xs); font-weight: var(--weight-semibold);
	cursor: pointer;
	font-family: inherit;
}
.boom-assinatura__submit:hover { filter: brightness(1.05); color: #fff; }
.boom-assinatura__submit:disabled { opacity: 0.6; cursor: default; }
.boom-assinatura__consent {
	font-size: 9.1px; color: rgba(255, 255, 255, 0.55);
	margin: var(--space-3) 0 0;
	line-height: var(--leading-relaxed);
	text-align: center;
}

/* [hidden] and an author display rule share specificity (0,1,0 each); the UA [hidden]
   rule loses to whichever rule comes later in the cascade unless overridden explicitly
   — same gotcha already documented on .boom-avaliacao-popup__pending/__success. Only
   __submitted still uses [hidden] now — __open has no closed/open toggle anymore, the
   popup shows the form directly. */
.boom-assinatura__submitted[hidden] { display: none; }

.boom-assinatura__submitted {
	background: rgba(255, 255, 255, 0.06);
	border-radius: var(--radius-md);
	padding: var(--space-7);
	margin-top: var(--space-6);
	display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-3);
}
.boom-assinatura__check {
	width: 38px; height: 38px;
	border-radius: 50%;
	background: rgba(37, 211, 102, 0.15);
	display: flex; align-items: center; justify-content: center;
}
.boom-assinatura__check i { font-size: 26px; color: #25D366; }
.boom-assinatura__submitted-title { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: #fff; margin: 0; }
.boom-assinatura__submitted-sub { font-size: var(--text-2xs); color: #C4B5FD; line-height: var(--leading-relaxed); margin: 0; }


/* "cashboom" home teaser (Boom Home.dc.html:704-737 — the cashboom half of the mockup's
   "programas boom" card pair; "boom plus" gets its own section/badge further below).
   Badge follows the same 24px icon-box pattern as every other .boom-section-title row
   (.boom-destaques__badge/.boom-confia__badge/.boom-assinatura__badge). */
.boom-cashboom__badge {
	width: 24px; height: 24px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface-tint);
	display: inline-flex; align-items: center; justify-content: center;
	box-shadow: var(--shadow-xs);
}
.boom-cashboom__badge i { font-size: 16.9px; color: var(--color-text-brand); }

.boom-cashboom__card {
	background: var(--color-bg-surface);
	border-radius: var(--radius-lg);
}
.boom-cashboom__title { font: var(--weight-semibold) var(--text-base) var(--font-display); color: var(--color-text-brand-deep); margin: 0; }
.boom-cashboom__desc { font-size: var(--text-xs); color: var(--color-text-secondary); margin: var(--space-2) 0 0; }
.boom-cashboom__list {
	list-style: disc; margin: var(--space-6) 0 var(--space-6); padding-left: 15px;
	font-size: var(--text-xs); color: var(--color-text-secondary); line-height: 1.65;
}
.boom-cashboom__link {
	display: inline-flex; align-items: center; justify-content: center; gap: var(--space-3);
	background: none; border: 1px solid var(--color-border-default); border-radius: var(--radius-sm);
	padding: var(--space-4) var(--space-8);
	cursor: pointer;
}
.boom-cashboom__link i { font-size: 12.35px; color: var(--color-text-brand-deep); }
.boom-cashboom__link span { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--color-text-brand-deep); }

/* "ver mais" popup — theme-owned, same centered-modal/border-top-accent/shared-backdrop
   convention as .boom-today-promo-popup (see initPopupBackdrop's anyDialogOpen check and
   boom.js's initCashboomPopup()). All money figures in the markup come from $boom_currency
   (get_woocommerce_currency_symbol()), never a literal "r$"/"R$" — see mapa_mental.md's
   dynamic-currency rule. */
.boom-cashboom-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	max-height: min(640px, calc(100% - 2 * var(--page-margin)));
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl);
	border-top: 4px solid var(--color-text-brand);
	padding: var(--space-9);
	box-sizing: border-box;
	box-shadow: var(--shadow-xl);
	flex-direction: column;
	/* Not overflow-y:auto — __body (inside __scroll below) scrolls itself.
	   overflow:hidden here just clips __scroll's corners to match the
	   popup's own border-radius. */
	overflow: hidden;
}
.boom-cashboom-popup.is-open { display: flex; }
/* Head/scroll/footer shape (2026-07-27, explanation.md #205) — mirrors
   parts/cart-popup.php's own __scroll exactly: __head (icon+title+close,
   below) and __btn (the "entendi" footer button) are now pinned flex
   siblings of __scroll, not descendants of it, so the scroll track
   (positioned against __scroll's own box) is confined to just the middle
   content and never runs behind either of them — the bug this replaced
   (close button/entendi both floated/scrolled inside the one region the
   track spanned, per the popup's own comment history before this date).
   __body is the actual [data-boom-popup-scrollbar-host] scrolling element;
   __scroll only sizes/positions it (and the track) within the space
   between __head and __btn. */
/* display:flex is explicit here, not left to a view-toggle rule like
   .boom-cart-popup__scroll gets it "for free" from (that popup's own
   .is-preview switch) — this popup has no such toggle, and flex-direction
   is a no-op on the display:block a bare <div> defaults to. Confirmed
   live: without this, __scroll silently stayed display:block and __body
   rendered at its unclamped natural height instead of scrolling.
   margin-right cancels the popup's own padding-right (var(--space-9)) for
   __scroll specifically — mandatory track-to-edge distance (CLAUDE.md #44),
   not a cart-popup-only nicety: without it the track sits a full
   var(--space-9)+6px in from the popup's true edge instead of just 6px,
   visibly further from the edge than the cart popup's own track (user
   report, explanation.md #206 — missed carrying this over when this popup
   was restructured in #205). */
.boom-cashboom-popup__scroll { display: flex; flex: 1; min-height: 0; flex-direction: column; position: relative; overflow: hidden; margin-right: calc(-1 * var(--space-9)); }

/* Real scroll thumb for popups whose content can overflow — project rule
   (see explanation.md): any popup marked [data-boom-popup-scrollbar-host]
   hides its own native scrollbar and gets this instead, same technique
   "monte seu pedido"'s combobox panels (.boom-combobox__scrollbar) already
   use — mobile Safari's OS-drawn overlay scrollbar has no CSS hook to force
   it to stay visible, so boom.js's initPopupScrollbar() positions this real
   thumb from the scrollable element's actual scrollTop/scrollHeight
   instead. Colors are this popup's own light-surface tint (not the
   combobox track's translucent white, which was designed for that
   component's violet background).
   [data-boom-popup-scrollbar-host] now marks the actual scrolling element
   (e.g. .boom-cashboom-popup__body, .boom-all-promos-popup__list), not
   the outer popup (2026-07-19 fix — see updatePopupScrollbar()'s own doc
   comment in boom.js for why the popup itself can't also host the track):
   flex:0 1 auto + min-height:0 is the same "hug content, shrink once the
   flex column parent runs out of room" pair .boom-combobox__list already
   uses, so this only actually scrolls once the popup's own max-height caps
   it. (Popups with persistent chrome around the scroll area, e.g.
   .boom-cashboom-popup__body / .boom-cart-popup__body, override this
   flex-basis to plain flex:1 instead — see each one's own comment.) */
[data-boom-popup-scrollbar-host] {
	flex: 0 1 auto;
	min-height: 0;
	overflow-y: auto;
	scrollbar-width: none; -ms-overflow-style: none;
	/* Same reason .boom-combobox__list needs this: without it, momentum
	   scrolling on iOS Safari can stall/feel unresponsive on a plain
	   overflow-y:auto element, which reads as "doesn't scroll" even though
	   scrollTop is moving. */
	-webkit-overflow-scrolling: touch;
}
[data-boom-popup-scrollbar-host]::-webkit-scrollbar { display: none; }
/* Overrides the shared rule's own flex:0 1 auto above — same specificity
   (both plain single-selector rules), so source order decides, which is
   why this has to come AFTER it, not just anywhere convenient (.boom-cart-
   popup__body doesn't need this same override placed here too — its own
   dedicated rule already lives further down the file, after this point,
   so source order already favors it there). See the shared rule's own
   comment above for why flex:1 is what these popups need instead. */
.boom-cashboom-popup__body { flex: 1; min-height: 0; padding-right: calc(var(--space-9) + 14px); }
/* Same override, same reason — see this block's own comment above. */
.boom-order-picker__list { flex: 1; min-height: 0; }
/* Same override, same reason — see this block's own comment above. */
.boom-service-rules-popup__body { flex: 1; min-height: 0; padding-right: calc(var(--space-9) + 14px); }
/* Same override, same reason — see this block's own comment above. */
.boom-order-picker__help-body { flex: 1; min-height: 0; padding-right: calc(var(--space-9) + 14px); }
/* Same override, same reason — see this block's own comment above.
   --space-8 here (not --space-9) matches .boom-all-promos-popup's own
   smaller padding, so the +14px gutter lines up with __scroll's own
   margin-right cancellation above. */
.boom-all-promos-popup__list { flex: 1; min-height: 0; padding-right: calc(var(--space-8) + 14px); }
.boom-popup-scrollbar {
	display: none;
	/* Flush (0, not var(--space-9)) — the track is now a sibling of the
	   padded scroll wrapper rather than living inside the same padding as
	   the old single-element popup, so it spans the outer popup's full
	   unpadded box (matching .boom-combobox__scrollbar's own top:0;bottom:0
	   against its equally unpadded .boom-combobox__panel). */
	position: absolute; top: 0; right: 6px; bottom: 0; width: 8px;
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-pill);
	pointer-events: none;
}
.boom-popup-scrollbar.is-visible { display: block; }
.boom-popup-scrollbar__thumb {
	position: absolute; left: 0; right: 0; top: 0;
	/* Deliberately the same solid brand color as the track thumbs elsewhere
	   in this design (not --color-border-default, a near-invisible tint
	   against this popup's own light --color-bg-surface-tint track — too
	   low-contrast to read as "moving" even when it correctly is). */
	background: var(--color-text-brand);
	border-radius: var(--radius-pill);
}
/* No longer position:absolute (was, before the head/scroll/footer
   restructure above) — inline now, inside __head's own flex row, same
   convention as .boom-cart-popup__close. A floating corner button doesn't
   have a fixed place in a flex column layout the way an in-flow one does,
   and was the direct cause of the track running up behind it. */
.boom-cashboom-popup__close {
	width: 24px; height: 24px; flex-shrink: 0;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	border: none; padding: 0; cursor: pointer;
}
.boom-cashboom-popup__close i { font-size: 16.9px; }
.boom-cashboom-popup__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-6); flex-shrink: 0; }
.boom-cashboom-popup__head-left { display: flex; align-items: center; gap: var(--space-4); min-width: 0; }
.boom-cashboom-popup__icon {
	width: 32px; height: 32px; flex-shrink: 0;
	border-radius: var(--radius-md);
	background: var(--color-bg-surface-tint);
	display: flex; align-items: center; justify-content: center;
}
.boom-cashboom-popup__icon i { font-size: 16px; color: var(--color-text-brand); }
.boom-cashboom-popup__title { font: var(--font-section-title); font-size: var(--text-base); color: var(--color-text-brand-deep); }
.boom-cashboom-popup__intro { font-size: var(--text-xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0 0 var(--space-6); }
.boom-cashboom-popup__note {
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-md);
	padding: var(--space-6);
	margin-bottom: var(--space-6);
}
.boom-cashboom-popup__note p { font-size: var(--text-2xs); color: var(--color-text-primary); line-height: 1.7; margin: 0; }
.boom-cashboom-popup__label {
	font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--color-text-brand-deep);
	text-transform: uppercase; letter-spacing: 0.3px; margin: 0 0 var(--space-4);
}
.boom-cashboom-popup__tiers { display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--space-6); }
.boom-cashboom-popup__tier {
	display: flex; align-items: center; justify-content: space-between;
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-sm);
	padding: var(--space-4) var(--space-6);
}
/* Only the "no bombinha yet" row needs a muted-red treatment — nothing else in the
   design system uses this shade, same one-off-literal-hex convention as
   .boom-assinatura__card's dark gradient (not worth a new token for a single row). */
.boom-cashboom-popup__tier--none { background: #FEF2F2; }
.boom-cashboom-popup__tier span:first-child { font-size: var(--text-2xs); color: var(--color-text-secondary); }
.boom-cashboom-popup__tier span:last-child { font-size: var(--text-2xs); color: var(--color-text-brand-deep); }
.boom-cashboom-popup__tier--none span:last-child { color: var(--color-text-secondary); font-weight: var(--weight-semibold); }
.boom-cashboom-popup__more { font-size: var(--text-2xs); color: var(--color-text-secondary); text-align: center; margin: 0 0 var(--space-6); }
.boom-cashboom-popup__reward {
	background: var(--color-bg-hero);
	border-radius: var(--radius-md);
	padding: var(--space-6);
	margin-bottom: var(--space-6);
	text-align: center;
}
.boom-cashboom-popup__reward strong { font-size: var(--text-xs); color: #fff; font-weight: var(--weight-semibold); display: block; }
.boom-cashboom-popup__reward span { font-size: var(--text-2xs); color: var(--violet-300); margin-top: var(--space-2); display: block; }
.boom-cashboom-popup__perk { display: flex; gap: var(--space-4); align-items: flex-start; margin-bottom: var(--space-5); }
.boom-cashboom-popup__perk i { font-size: 14px; color: var(--color-text-brand-deep); flex-shrink: 0; margin-top: 1px; }
.boom-cashboom-popup__perk p { font-size: var(--text-2xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0; }
.boom-cashboom-popup__btn {
	flex-shrink: 0; width: 100%; margin-top: var(--space-6);
	background: var(--color-bg-cta); color: #fff;
	border: none; border-radius: var(--radius-md);
	padding: var(--space-6); box-sizing: border-box;
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	text-align: center; cursor: pointer;
}
.boom-cashboom-popup__btn:hover { filter: brightness(1.05); }


/* Checkout page's "prévia do link informado" popup (page-finalizar-
   compra.php, opened by woocommerce/cart/cart.php's cart-item thumbnails —
   see boom.js's initLinkPreviewPopup()). Same centered-modal/shared-backdrop
   box model as .boom-cashboom-popup, but its own __head shape (icon+title
   left, close button inline right — not the absolute-positioned corner
   button the cards-grid popups use) since the mockup draws it as a single
   flex row, not a separate title block under a floating close button. */
.boom-link-preview-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	max-height: calc(100% - 2 * var(--page-margin));
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl);
	padding: var(--space-9) var(--space-8);
	box-sizing: border-box;
	box-shadow: var(--shadow-xl);
	flex-direction: column;
	overflow-y: auto;
}
.boom-link-preview-popup.is-open { display: flex; }
.boom-link-preview-popup__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-6); }
.boom-link-preview-popup__head-left { display: flex; align-items: center; gap: var(--space-4); }
.boom-link-preview-popup__head-left i { font-size: 16px; color: var(--color-icon-checkout-info); }
.boom-link-preview-popup__head-left span { font-size: var(--text-base); font-weight: var(--weight-bold); color: var(--color-text-primary); }
.boom-link-preview-popup__close {
	background: none; border: none; padding: 2px; cursor: pointer;
	display: inline-flex; color: var(--color-text-primary);
}
.boom-link-preview-popup__close i { font-size: 16px; }
.boom-link-preview-popup__cover {
	width: 100%; aspect-ratio: 4 / 3;
	border-radius: var(--radius-md);
	background: var(--ink-900);
	display: flex; align-items: center; justify-content: center;
	overflow: hidden;
}
.boom-link-preview-popup__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Post caption / profile bio — same role as #popup_servicos_home > span.lower_text
   in the home "confirme o link" popup (boom.css ~line 1363), same text style,
   just margin-top instead of margin-bottom since this popup is a flex column
   (margins don't collapse in flex, so each row owns its own top gap). Hidden
   via [data-boom-link-preview-caption][hidden] when there's no caption, same
   convention as __handle below. */
.boom-link-preview-popup__caption { margin-top: var(--space-6); font-size: var(--text-xs); color: var(--color-text-primary); text-align: center; line-height: var(--leading-relaxed); }
.boom-link-preview-popup__handle { text-align: center; font-size: var(--text-base); font-weight: var(--weight-bold); color: var(--color-text-brand); margin-top: var(--space-4); }
.boom-link-preview-popup__stats {
	display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
	gap: var(--space-3) var(--space-6); margin-top: var(--space-4);
}
.boom-link-preview-popup__stats span { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); color: var(--color-text-secondary); }
.boom-link-preview-popup__stats i { font-size: 13px; color: var(--color-text-secondary); }
.boom-link-preview-popup__link {
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-sm);
	padding: var(--space-5) var(--space-6);
	margin-top: var(--space-6);
	text-align: center;
}
.boom-link-preview-popup__link span { font-size: var(--text-xs); color: var(--color-text-brand); word-break: break-all; }

/* Profile-type content (perfil/canal) reads identity-first — handle + follower
   count before the bio text, like a profile card. Post/media content (feed
   post, video) keeps the default DOM order (cover, caption, handle, stats,
   link) untouched. .is-profile-preview is toggled by initLinkPreviewPopup()
   (boom.js) from data.isProfile — same distinction popup_confirmacao_de_link()
   already applies live in home.js via dto.endpoint === 'profile'. cover/link
   need an explicit order so they stay pinned first/last once the other three
   start moving (unset flex items default to order:0, same as cover). */
.boom-link-preview-popup__cover { order: 0; }
.boom-link-preview-popup__link { order: 4; }
.boom-link-preview-popup.is-profile-preview .boom-link-preview-popup__handle { order: 1; }
/* Bio before follower count for profile-type content (2026-07-22 refinement —
   was stats-then-caption, now caption-then-stats). */
.boom-link-preview-popup.is-profile-preview .boom-link-preview-popup__caption { order: 2; }
.boom-link-preview-popup.is-profile-preview .boom-link-preview-popup__stats { order: 3; }


/* Cards grid popups (mais vendidos, status de serviços, desconto no pix,
   stories e avisos, ganhe brindes) — all five share the exact box model
   already established by .boom-cashboom-popup (centered, border-top brand
   accent, shared backdrop), so the shape is declared once via a grouped
   selector; only each popup's own content classes differ below. */
.boom-bestsellers-popup,
.boom-status-popup,
.boom-brinde-popup,
.boom-modo-escuro-popup,
.boom-myaccount-expired-popup,
.boom-myaccount-whereuse-popup,
.boom-cart-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	max-height: min(640px, calc(100% - 2 * var(--page-margin)));
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl);
	border-top: 4px solid var(--color-text-brand-deep);
	padding: var(--space-9);
	box-sizing: border-box;
	box-shadow: var(--shadow-xl);
	flex-direction: column;
	overflow-y: auto;
}
.boom-bestsellers-popup.is-open,
.boom-status-popup.is-open,
.boom-brinde-popup.is-open,
.boom-modo-escuro-popup.is-open,
.boom-myaccount-expired-popup.is-open,
.boom-myaccount-whereuse-popup.is-open,
.boom-cart-popup.is-open { display: flex; }

/* Real always-visible scrollbar (CLAUDE.md #44) for the 3 popups in the
   shared group above whose own list content can genuinely grow long
   (bestsellers/status are admin-managed, myaccount-expired accumulates
   over a customer's lifetime) — brinde/modo-escuro/myaccount-whereuse
   stay on the shared group's plain overflow-y:auto since their content is
   always short/fixed. Cancels the shared group's own padding/overflow-y
   for these 3 specifically — padding moves to each one's own __scroll
   wrapper instead (same convention as .boom-cashboom-popup/__scroll),
   which also hosts [data-boom-popup-scrollbar-host] since none of these 3
   have persistent chrome outside the scrolling area (unlike
   .boom-cart-popup, which needed a dedicated head/footer-free wrapper —
   see that popup's own comment for why). */
.boom-bestsellers-popup,
.boom-status-popup,
.boom-myaccount-expired-popup { padding: 0; overflow: hidden; }
.boom-bestsellers-popup__scroll,
.boom-status-popup__scroll,
.boom-myaccount-expired-popup__scroll { padding: var(--space-9); }

.boom-bestsellers-popup__close,
.boom-status-popup__close,
.boom-brinde-popup__close,
.boom-modo-escuro-popup__close,
.boom-myaccount-expired-popup__close,
.boom-myaccount-whereuse-popup__close {
	position: absolute; top: var(--space-4); right: var(--space-4);
	width: 24px; height: 24px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	border: none; padding: 0; cursor: pointer;
}
.boom-bestsellers-popup__close i,
.boom-status-popup__close i,
.boom-brinde-popup__close i,
.boom-modo-escuro-popup__close i,
.boom-myaccount-expired-popup__close i,
.boom-myaccount-whereuse-popup__close i { font-size: 16.9px; }

/* mandatory __head pattern (explanation.md): align-items:center, matching
   .boom-all-promos-popup__head, for the titles here that are always
   single-line at this popup's 320px width ("mais vendidos", "status dos
   serviços") — flex-start here made the icon sit visibly lower than the
   title's vertical center (2026-07-19 fix, explicit user report). */
.boom-bestsellers-popup__head,
.boom-status-popup__head,
.boom-modo-escuro-popup__head {
	display: flex; align-items: center; gap: var(--space-4);
	margin-bottom: var(--space-6); padding-right: var(--space-9);
	flex-shrink: 0;
}
/* flex-start stays here: "ganhe brinde fazendo pedidos" genuinely wraps
   to two lines at this popup's 320px width — center would vertically
   straddle the icon between the two title lines instead of aligning it
   with the top one. */
.boom-brinde-popup__head {
	display: flex; align-items: flex-start; gap: var(--space-4);
	margin-bottom: var(--space-6); padding-right: var(--space-9);
	flex-shrink: 0;
}
.boom-bestsellers-popup__icon,
.boom-status-popup__icon,
.boom-brinde-popup__icon,
.boom-modo-escuro-popup__icon,
.boom-cart-popup__icon {
	width: 32px; height: 32px; flex-shrink: 0;
	border-radius: var(--radius-md);
	background: var(--color-bg-surface-tint);
	display: flex; align-items: center; justify-content: center;
}
.boom-bestsellers-popup__icon i,
.boom-status-popup__icon i,
.boom-brinde-popup__icon i,
.boom-modo-escuro-popup__icon i,
.boom-cart-popup__icon i { font-size: 16px; color: var(--color-text-brand); }

.boom-bestsellers-popup__title,
.boom-status-popup__title,
.boom-brinde-popup__title,
.boom-modo-escuro-popup__title,
.boom-cart-popup__title { font: var(--font-section-title); font-size: var(--text-base); color: var(--color-text-brand-deep); }

/* "meu carrinho" popup (parts/cart-popup.php) — unlike the other card
   popups above (one scrolling list, nothing else), this one has a pinned
   "finalizar compra" button below a scrolling body, so it overrides the
   shared group's own overflow-y:auto (root) in favor of scrolling only
   __body — same "fixed head/footer, scrolling middle" shape already used
   by the qty/service picker sheets (front-page.php's order builder).
   Head/close/back button aren't in the shared cardPopupClasses group above
   (2026-07-27 change) — this popup's head needs a back+close button PAIR
   in preview view, which the shared group's single absolute-positioned
   corner button can't express, so it gets its own inline flex row instead. */
/* Sized bigger than the shared group's own width/max-height (2026-07-27,
   user report: a full cart forced internal scrolling well before running
   out of actual free space on screen) — ~5% top/bottom margin instead of
   the shared 640px cap, so the popup grows with the item list up to
   almost the full viewport before its own __body scroll kicks in. Width
   goes up another 20% (320px -> 384px) from 480px up (desktop/tablet
   shell breakpoint, desktop-nav.css) only — mobile's width is unchanged. */
.boom-cart-popup { overflow-y: hidden; max-height: calc(100% - 2 * 5%); }
@media (min-width: 480px) {
	.boom-cart-popup { width: min(384px, calc(100% - 2 * var(--page-margin))); }
}
.boom-cart-popup__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-6); flex-shrink: 0; }
.boom-cart-popup__head-left { display: flex; align-items: center; gap: var(--space-4); min-width: 0; }
.boom-cart-popup__head-actions { display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; }
.boom-cart-popup__close,
.boom-cart-popup__back {
	width: 24px; height: 24px; flex-shrink: 0;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	border: none; padding: 0; cursor: pointer;
}
.boom-cart-popup__close i,
.boom-cart-popup__back i { font-size: 16.9px; }
/* [hidden] and .boom-cart-popup__back above are the same specificity
   (0,1,0) — the UA stylesheet's [hidden]{display:none} loses that tie to
   this later author rule's display:inline-flex, so the plain hidden
   attribute alone doesn't actually hide the header's back button between
   views. This attribute-on-class selector outweighs it. */
.boom-cart-popup__back[hidden] { display: none; }
/* __scroll is the flex item (not __body itself) so the real scrollbar
   track below can be positioned against a box that spans exactly the
   scrolling area — not the whole popup, which also has a non-scrolling
   head/footer around it (explanation.md #203). Same "flex:1;min-height:0"
   pattern the outer popup already uses to size __scroll itself, just
   nested one level deeper: __scroll needs its own flex-direction:column
   (easy to forget, since track is position:absolute and doesn't need a
   direction) so __body — a normal in-flow flex child, not absolutely
   positioned — can use that same pattern to fill it. (A first attempt
   used height:100%/position:absolute on __body instead; both silently
   collapsed __scroll to 0 height, confirmed live — an auto-sized flex
   column can't "grow into" space when its own only in-flow content has
   flex-basis 0 and nothing else establishes a size. Plain flex:1 works
   because it's the exact same mechanism already proven one level up.)
   __body's extra right padding reserves the track's own lane so it never
   overlaps item text/prices — same asymmetric-padding technique
   .boom-combobox__list already uses for its own scroll lane. */
/* margin-right cancels the popup's own padding-right (var(--space-9)) for
   __scroll specifically, extending it flush to the popup's true right
   edge — the track (right:6px, below) is positioned against __scroll's
   own box, so it was sitting 20px+6px in from the real edge, too close to
   the item text next to it (user report + screenshot). __body's
   padding-right grows by that same reclaimed amount on top of its
   original 14px track-lane gutter, so the actual item text/prices stay
   at the exact same visual position as before — only the track itself
   moves, into the space the popup's own padding otherwise left empty. */
.boom-cart-popup__scroll { flex: 1; min-height: 0; flex-direction: column; position: relative; overflow: hidden; margin-right: calc(-1 * var(--space-9)); }
.boom-cart-popup__body { flex: 1; min-height: 0; overflow-y: auto; padding-right: calc(var(--space-9) + 14px); }
.boom-cart-popup__body .boom-cart-item:first-of-type { padding-top: 0; }
.boom-cart-popup__empty {
	display: flex; flex-direction: column; align-items: center; gap: var(--space-4);
	padding: var(--space-9) 0;
	text-align: center; color: var(--color-text-secondary); font-size: var(--text-sm);
}
.boom-cart-popup__empty i { font-size: 28px; color: var(--color-text-muted); }
.boom-cart-popup__checkout-btn {
	display: flex; width: 100%; align-items: center; justify-content: center;
	flex-shrink: 0; margin-top: var(--space-6);
	font: var(--font-button);
	text-align: center; font-weight: var(--weight-bold);
	background: var(--color-bg-cta); color: #fff;
	border-radius: 10px;
	padding: 13px var(--space-9);
	box-shadow: var(--shadow-button);
	text-decoration: none;
	transition: transform var(--duration-fast) var(--ease-standard), filter var(--duration-fast) var(--ease-standard);
}
.boom-cart-popup__checkout-btn:hover { filter: brightness(1.05); color: #fff; }
.boom-cart-popup__checkout-btn:active { transform: scale(0.97); }
.boom-cart-popup.is-empty .boom-cart-popup__checkout-btn { display: none; }

/* "prévia do link informado" internal view (2026-07-27, explanation.md
   #201) — single-modal navigation instead of a second stacked popup.
   Hidden by default; .is-preview (root, toggled by initCartPopup()) swaps
   this in and hides __body/__checkout-btn instead. Field elements below
   reuse parts/link-preview-popup.php's own .boom-link-preview-popup__*
   classes verbatim (cover/caption/handle/stats/link — those selectors
   aren't scoped to require that popup as an ancestor, so they apply here
   for free); only the container, the "será entregue" label/service name,
   and the profile-vs-post reordering need their own rules, scoped under
   this container instead of under .boom-link-preview-popup. */
.boom-cart-popup__scroll,
.boom-cart-popup__checkout-btn { display: none; }
.boom-cart-popup:not(.is-preview) .boom-cart-popup__scroll { display: flex; }
.boom-cart-popup:not(.is-preview):not(.is-empty) .boom-cart-popup__checkout-btn { display: flex; }
.boom-cart-popup__preview { display: none; flex-direction: column; overflow-y: auto; }
.boom-cart-popup.is-preview .boom-cart-popup__preview { display: flex; }
.boom-cart-popup__preview-label { font-size: var(--text-2xs); color: var(--color-text-muted); }
.boom-cart-popup__preview-service { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--color-text-secondary); margin-bottom: var(--space-6); }
.boom-cart-popup__preview .boom-link-preview-popup__cover { order: 0; }
.boom-cart-popup__preview .boom-link-preview-popup__link { order: 4; }
.boom-cart-popup__preview.is-profile-preview .boom-link-preview-popup__handle { order: 1; }
.boom-cart-popup__preview.is-profile-preview .boom-link-preview-popup__caption { order: 2; }
.boom-cart-popup__preview.is-profile-preview .boom-link-preview-popup__stats { order: 3; }
.boom-cart-popup__back-pill {
	order: 5;
	display: flex; align-items: center; justify-content: center; gap: var(--space-3);
	width: 100%; margin-top: var(--space-8); flex-shrink: 0;
	background: linear-gradient(135deg, var(--violet-500), var(--violet-600));
	color: #fff; border: none; border-radius: var(--radius-pill);
	padding: 13px var(--space-9);
	font: var(--font-button); text-align: center; font-weight: var(--weight-bold);
	box-shadow: var(--shadow-button);
	cursor: pointer;
	transition: transform var(--duration-fast) var(--ease-standard);
}
.boom-cart-popup__back-pill:active { transform: scale(0.97); }

/* "mais vendidos" popup content: a plain row per bestseller (icon, name,
   price via boom_from_price(), "comprar" link to the real product). */
.boom-bestsellers-popup__list { display: flex; flex-direction: column; }
.boom-bestseller-row {
	display: flex; align-items: center; gap: var(--space-5);
	padding: var(--space-5) 0;
	border-top: var(--border-hairline);
}
.boom-bestseller-row:first-child { border-top: none; padding-top: 0; }
.boom-bestseller-row__icon {
	width: 34px; height: 34px; flex-shrink: 0;
	border-radius: var(--radius-md);
	background: var(--color-bg-surface-tint);
	display: flex; align-items: center; justify-content: center;
}
.boom-bestseller-row__icon i { font-size: 15.6px; color: var(--color-text-brand); }
.boom-bestseller-row__body { flex: 1; min-width: 0; }
.boom-bestseller-row__name {
	font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--color-text-primary);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0;
}
.boom-bestseller-row__price { font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--color-text-brand-deep); margin: 2px 0 0; }
.boom-bestseller-row__cta {
	flex-shrink: 0;
	background: var(--color-bg-cta); color: #fff;
	border: none; border-radius: var(--radius-pill);
	padding: var(--space-4) var(--space-6);
	font-size: var(--text-2xs); font-weight: var(--weight-bold); font-family: inherit;
	text-decoration: none;
	cursor: pointer;
}
.boom-bestsellers-popup__empty,
.boom-status-popup__empty {
	font-size: var(--text-xs); color: var(--color-text-secondary);
	text-align: center; padding: var(--space-6) 0; margin: 0;
}
.boom-bestsellers-popup__tip {
	display: flex; align-items: flex-start; justify-content: center; gap: 3px;
	flex-shrink: 0; margin: var(--space-5) 0 0; text-align: center;
	background: var(--color-bg-tip); border: var(--border-hairline); border-color: var(--color-border-tip);
	border-radius: var(--radius-sm);
	padding: var(--space-4) var(--space-5);
	font-size: var(--text-2xs); color: var(--color-text-tip);
}
.boom-bestsellers-popup__tip i { color: var(--color-text-tip); flex-shrink: 0; }

/* "status de serviços" popup rows — boom-core's service-status module, one
   row per entry, colored per its type's style bucket (success/warning),
   same semantic color tokens as .boom-status-box--success/--warning (not new
   colors). Spaced like .boom-bestseller-row (hairline divider + generous
   vertical padding) rather than the tighter ticker-box treatment, since
   these rows are all visible at once here (no auto-cycling). */
.boom-status-popup__list { display: flex; flex-direction: column; }
/* Values scaled 1.3x from Boom Home.dc.html's statusModal rows (2026-07-25) -
   see the ticker's own comment above for the shared factor/rationale. */
.boom-status-popup__row {
	display: flex; align-items: flex-start; gap: 10.4px;
	padding: 11.7px 14.3px;
	border-radius: 11.7px;
	margin-bottom: 9.1px;
}
.boom-status-popup__row:last-child { margin-bottom: 0; }
.boom-status-popup__row i { flex-shrink: 0; font-size: 18.2px; margin-top: 1px; }
.boom-status-popup__row-body { display: flex; flex-direction: column; gap: 3.9px; min-width: 0; }
/* Tag + date on one line (row-head), title below on its own line - one line
   shorter per row than the old group-label layout. flex-start + gap, NOT
   space-between: confirmed against the mockup's real inline styles, the
   date sits close to the tag rather than pinned to the card's right edge. */
.boom-status-popup__row-head { display: flex; align-items: center; flex-wrap: wrap; gap: 7.8px; }
.boom-status-popup__row-text { font-size: var(--text-xs); font-weight: var(--weight-medium); }
.boom-status-popup__row-date { font-size: 11.05px; opacity: 0.75; flex-shrink: 0; white-space: nowrap; }
/* Shared by both status surfaces - see .boom-status-box__row-tag (not a new
   visual language). Both now nest the tag inside a row-head alongside the
   date rather than stacking it alone, so no align-self/margin-bottom is
   needed here anymore - just a padding difference between the two (popup's
   own mockup section uses slightly more horizontal padding than the
   ticker's). */
.boom-status-box__row-tag,
.boom-status-popup__row-tag {
	display: inline-block;
	border-radius: var(--radius-pill);
	padding: 2.6px 7.8px;
	font-size: 9.75px; font-weight: var(--weight-bold);
	text-transform: uppercase; letter-spacing: 0.3px;
}
.boom-status-popup__row-tag { padding: 2.6px 9.1px; }
.boom-status-popup__row--success {
	background: var(--color-bg-success); border: var(--border-hairline); border-color: var(--color-border-success);
	color: var(--color-text-success);
}
.boom-status-popup__row--success i { color: var(--color-text-success); }
.boom-status-popup__row--success .boom-status-popup__row-tag { background: var(--color-bg-success-strong); color: var(--color-text-success); }
.boom-status-popup__row--warning {
	background: var(--color-bg-warning); border: var(--border-hairline); border-color: var(--color-border-warning);
	color: var(--color-text-warning);
}
.boom-status-popup__row--warning i { color: var(--color-text-warning); }
.boom-status-popup__row--warning .boom-status-popup__row-tag { background: var(--color-bg-warning-strong); color: var(--color-text-warning); }

/* "stories e avisos" popup content: same sub/watch-label treatment as
   .boom-destaques' on-page header; the circle row itself is unstyled here
   since it reuses .boom-destaque-row/.boom-destaque-circle as-is. */
.boom-status-popup__sub { font: var(--font-caption); color: var(--color-text-secondary); margin: 0 0 var(--space-6); }

/* "ganhe brindes" popup content: real content stays [hidden] behind the "em
   breve" line — see front-page.php's own comment on .boom-brinde-popup__content
   for why. Steps/CTA styles are ready for whenever that content is unhidden.
   .boom-modo-escuro-popup__soon shares this same treatment — dark mode has
   no real implementation yet either. */
.boom-brinde-popup__soon,
.boom-modo-escuro-popup__soon {
	font-size: var(--text-xs); color: var(--color-text-secondary);
	text-align: center; padding: var(--space-6) 0; margin: 0;
}
.boom-brinde-popup__desc { font-size: var(--text-xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0 0 var(--space-6); }
.boom-brinde-popup__steps { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-6); }
.boom-brinde-popup__step { flex: 1; display: flex; flex-direction: column; align-items: center; gap: var(--space-3); }
.boom-brinde-popup__step-bar { width: 100%; height: 5px; border-radius: var(--radius-pill); background: var(--color-bg-surface-tint); }
.boom-brinde-popup__step-dot {
	width: 22px; height: 22px;
	border-radius: 50%;
	background: var(--color-bg-surface-tint);
	display: flex; align-items: center; justify-content: center;
}
.boom-brinde-popup__step-dot i { font-size: 11px; color: var(--color-text-secondary); }
.boom-brinde-popup__cta {
	display: flex; align-items: center; justify-content: center; gap: var(--space-3);
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-md);
	padding: var(--space-6);
	font-size: var(--text-2xs); font-weight: var(--weight-bold); color: var(--color-text-brand-deep);
	text-decoration: none;
}


/* "boom plus" home teaser (Boom Home.dc.html:739-755 — the other half of the mockup's
   "programas boom" card pair). No outer .boom-section-title header/badge here — see
   front-page.php's own comment on this section for why (removed 2026-07-17, was an
   unrequested duplicate of the card's own internal title). Card reuses the exact
   literal dark gradient already established by .boom-assinatura__card (not
   --color-bg-hero — see that rule's own comment for why) since the mockup uses the
   identical pair of hex values here too. */

/* padding: 12px is a literal match to the mockup (var(--space-8) would be 16px) —
   worth being exact here, since linear-gradient's rendered color distribution is
   dimension-dependent: a shorter/narrower box shows a visibly different slice of a
   155deg gradient than a taller one even with identical color stops, so matching the
   mockup's own box proportions (padding + the icon/title row below) is what actually
   makes this card's background read the same as the reference, not just the gradient
   declaration matching in isolation. */
.boom-boomplus__card {
	background: linear-gradient(155deg, #241F38, #1F1B2E);
	border-radius: var(--radius-lg);
	padding: var(--space-6);
}
.boom-boomplus__head { display: flex; align-items: center; gap: var(--space-4); }
.boom-boomplus__icon {
	width: 30px; height: 30px; flex-shrink: 0;
	border-radius: var(--radius-sm);
	background: rgba(255, 255, 255, 0.08);
	display: flex; align-items: center; justify-content: center;
}
.boom-boomplus__icon i { font-size: 16px; color: var(--violet-300); }
.boom-boomplus__title { font: var(--weight-bold) var(--text-base) var(--font-display); color: #fff; margin: 0; }
.boom-boomplus__desc { font-size: var(--text-xs); color: var(--violet-300); margin: 5px 0 0; }
.boom-boomplus__list {
	list-style: disc; margin: var(--space-6) 0 var(--space-7); padding-left: 15px;
	font-size: var(--text-xs); color: var(--violet-300); line-height: 1.65;
}
.boom-boomplus__link {
	display: inline-flex; align-items: center; justify-content: center; gap: var(--space-3);
	background: none; border: 1px solid rgba(255, 255, 255, 0.35); border-radius: var(--radius-sm);
	padding: var(--space-4) var(--space-8);
	cursor: pointer;
}
.boom-boomplus__link i { font-size: 12.35px; color: #fff; }
.boom-boomplus__link span { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: #fff; }

/* "boom plus" info popup — same centered-modal/border-top-accent/shared-backdrop
   convention as .boom-cashboom-popup/.boom-today-promo-popup, but a dark surface
   (mockup uses a flat #1F1B2E card here, not the light surface the other popups use —
   var(--violet-900) is that same hex as a token) with a light-violet top accent
   instead of the brand-violet one. */
.boom-boomplus-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	max-height: min(640px, calc(100% - 2 * var(--page-margin)));
	background: var(--violet-900);
	border-radius: var(--radius-xl);
	border-top: 4px solid var(--violet-300);
	padding: var(--space-9);
	box-sizing: border-box;
	box-shadow: var(--shadow-xl);
	flex-direction: column;
	overflow-y: auto;
}
.boom-boomplus-popup.is-open { display: flex; }
.boom-boomplus-popup__close {
	position: absolute; top: var(--space-4); right: var(--space-4);
	width: 24px; height: 24px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: rgba(255, 255, 255, 0.08);
	color: var(--violet-300);
	border: none; padding: 0; cursor: pointer;
}
.boom-boomplus-popup__close i { font-size: 16.9px; }
.boom-boomplus-popup__head { display: flex; align-items: center; gap: var(--space-4); margin-bottom: var(--space-2); padding-right: var(--space-9); }
.boom-boomplus-popup__icon {
	width: 32px; height: 32px; flex-shrink: 0;
	border-radius: var(--radius-md);
	background: rgba(255, 255, 255, 0.08);
	display: flex; align-items: center; justify-content: center;
}
.boom-boomplus-popup__icon i { font-size: 16px; color: var(--violet-300); }
.boom-boomplus-popup__title { font: var(--font-section-title); font-size: var(--text-base); color: #fff; }
.boom-boomplus-popup__intro { font-size: var(--text-xs); color: var(--violet-300); line-height: var(--leading-relaxed); margin: 0 0 var(--space-6); }
.boom-boomplus-popup__perks { display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--space-7); }
.boom-boomplus-popup__perk { display: flex; gap: var(--space-4); align-items: flex-start; }
.boom-boomplus-popup__perk--last { margin-bottom: var(--space-5); }
.boom-boomplus-popup__perk i { font-size: 15px; color: var(--violet-300); flex-shrink: 0; margin-top: 1px; }
.boom-boomplus-popup__perk p { font-size: var(--text-2xs); color: #fff; line-height: var(--leading-relaxed); margin: 0; }
.boom-boomplus-popup__perk--last p { color: var(--violet-300); }
.boom-boomplus-popup__note {
	background: rgba(255, 255, 255, 0.06);
	border-radius: var(--radius-md);
	padding: var(--space-6);
	margin-bottom: var(--space-6);
	text-align: center;
}
.boom-boomplus-popup__note p { font-size: var(--text-2xs); color: #fff; font-weight: var(--weight-semibold); margin: 0; }
.boom-boomplus-popup__cta {
	display: flex; align-items: center; justify-content: center; gap: var(--space-3);
	width: 100%; margin-bottom: var(--space-5); box-sizing: border-box;
	background: var(--color-bg-surface); color: var(--color-text-primary);
	border: none; border-radius: var(--radius-md);
	padding: var(--space-6);
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	text-decoration: none; cursor: pointer;
}
.boom-boomplus-popup__cta:hover { filter: brightness(0.97); }
.boom-boomplus-popup__dismiss {
	display: block; width: 100%;
	background: none; border: 1px solid rgba(255, 255, 255, 0.25); border-radius: var(--radius-md);
	padding: var(--space-5);
	font-size: var(--text-xs); font-weight: var(--weight-medium);
	color: var(--violet-300);
	text-align: center; cursor: pointer;
}


/* "dúvidas frequentes" (Boom Home.dc.html:758-805) — compact list-row accordion, a
   different visual language from .boom-hub__acc-* (no icon/subtitle per row here,
   just a question + chevron). Reuses the same generic [data-boom-accordion]/
   [data-open] JS hook and chevron-rotate/height-reveal convention as .boom-hub__acc-*
   (see that rule's own comment) — only the row styling itself is new. */
/* #faq anchor target (menu sheet's "dúvidas frequentes" link) — same
   sticky-header offset as #monte-pedido above. */
#faq { scroll-margin-top: 74px; }
/* Boxed title row, same treatment as .boom-confia .boom-section-title above. */
.boom-faq-section .boom-section-title {
	width: 100%;
	box-sizing: border-box;
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-md);
	padding: 9px 13px;
}
.boom-faq__badge {
	width: 24px; height: 24px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface);
	display: inline-flex; align-items: center; justify-content: center;
	box-shadow: var(--shadow-xs);
}
.boom-faq__badge i { font-size: 16.9px; color: var(--color-text-brand); }

.boom-faq {
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	border-radius: var(--radius-lg);
	overflow: hidden;
}
.boom-faq__item + .boom-faq__item { border-top: var(--border-hairline); }
.boom-faq__question {
	display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
	width: 100%;
	background: none; border: none; margin: 0;
	padding: var(--space-5) var(--space-6);
	cursor: pointer;
	text-align: left;
	font: inherit;
}
.boom-faq__question span { font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--color-text-primary); }
.boom-faq__question i { flex-shrink: 0; font-size: 11px; color: var(--color-text-secondary); transition: transform var(--duration-base) var(--ease-standard); }
.boom-faq__item[data-open] .boom-faq__question i { transform: rotate(180deg); color: var(--color-text-brand-deep); }
.boom-faq__answer {
	max-height: 0; overflow: hidden; opacity: 0;
	padding: 0 var(--space-6);
	font-size: var(--text-2xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed);
	transition: max-height var(--duration-slow) var(--ease-standard), opacity var(--duration-base) var(--ease-standard), padding var(--duration-slow) var(--ease-standard);
}
.boom-faq__answer p { margin: 0 0 var(--space-4); }
.boom-faq__answer p:last-child { margin-bottom: 0; }
.boom-faq__item[data-open] .boom-faq__answer {
	max-height: 3000px; opacity: 1;
	padding: 0 var(--space-6) var(--space-6);
}


/* "evite golpes" footer trust block (Boom Home.dc.html:807-877). Outer <section>
   reuses the exact literal dark gradient already established by .boom-assinatura__card/
   .boom-boomplus__card (#241F38 -> #1F1B2E) — same convention, same comment applies:
   not --color-bg-hero, not a new token, since nothing else in the design system uses
   this exact pair. Overrides .boom-card's light default background. */
.boom-footer-trust.boom-card {
	background: linear-gradient(155deg, #241F38, #1F1B2E);
	border: none;
	padding: var(--space-7);
}
.boom-footer-trust__alert {
	background: rgba(255, 255, 255, 0.05);
	border-radius: var(--radius-md);
	padding: var(--space-5);
	margin-bottom: var(--space-6);
}
/* Head (icon + title) now follows the exact same shape as .boom-boomplus__head/
   .boom-boomplus__icon/.boom-boomplus__title (2026-07-19, explicit user
   request to match that pattern) — align-items:center, not flex-start:
   "evite golpes" is always a single line, same reasoning the project's
   mandatory __head rule already applies elsewhere (explanation.md §58/§71). */
.boom-footer-trust__alert-head { display: flex; align-items: center; gap: var(--space-4); margin-bottom: 3px; }
.boom-footer-trust__alert-icon {
	width: 30px; height: 30px; flex-shrink: 0;
	border-radius: var(--radius-sm);
	background: rgba(255, 255, 255, 0.08);
	display: flex; align-items: center; justify-content: center;
}
.boom-footer-trust__alert-icon i { font-size: 16px; color: var(--violet-300); }
.boom-footer-trust__alert-title { font: var(--weight-bold) var(--text-base) var(--font-display); color: #fff; margin: 0; }
.boom-footer-trust__alert-sub { font-size: var(--text-2xs); color: var(--violet-300); line-height: var(--leading-relaxed); margin: 0; }

/* Nested inside .boom-footer-trust__alert now (2026-07-19, see front-page.php's
   own comment) — margin-top separates it from __alert-sub above, replacing the
   margin-bottom this used when it was still a standalone sibling element. */
.boom-footer-trust__contacts { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-5); }
.boom-footer-trust__contact {
	display: flex; align-items: center; gap: var(--space-3);
	font-size: var(--text-2xs);
	text-decoration: none;
}
.boom-footer-trust__contact:hover { text-decoration: underline; }
.boom-footer-trust__contact i { color: var(--violet-300); }

.boom-footer-trust__instagram {
	display: flex; align-items: center; gap: var(--space-5);
	text-decoration: none;
	background: rgba(255, 255, 255, 0.05);
	border-radius: var(--radius-md);
	padding: var(--space-5);
	margin-bottom: var(--space-6);
}
.boom-footer-trust__instagram-icon {
	width: 30px; height: 30px; flex-shrink: 0;
	border-radius: var(--radius-sm);
	background: linear-gradient(135deg, #F58529, #DD2A7B, #8134AF);
	display: flex; align-items: center; justify-content: center;
}
.boom-footer-trust__instagram-icon i { color: #fff; }
.boom-footer-trust__instagram-text { flex: 1; min-width: 0; }
.boom-footer-trust__instagram-title { display: block; font-size: var(--text-base); font-weight: var(--weight-bold); color: #fff; }
.boom-footer-trust__instagram-handle { display: block; font-size: 8px; color: var(--violet-300); margin-top: 1px; }
.boom-footer-trust__instagram > i { flex-shrink: 0; color: var(--violet-300); }

.boom-footer-trust__badges { display: flex; gap: var(--space-3); margin-bottom: var(--space-6); }
.boom-footer-trust__badge {
	flex: 1;
	background: rgba(255, 255, 255, 0.05);
	border-radius: var(--radius-md);
	padding: var(--space-4) var(--space-3);
	display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
	text-align: center;
}
.boom-footer-trust__badge i { color: #4ADE80; }
.boom-footer-trust__badge span { font-size: 7px; font-weight: var(--weight-semibold); color: var(--violet-300); line-height: 1.3; }

.boom-footer-trust__payments { padding-top: var(--space-6); border-top: 1px solid rgba(255, 255, 255, 0.1); margin-bottom: var(--space-6); }
.boom-footer-trust__payments-label { font-size: 7px; font-weight: var(--weight-semibold); color: var(--violet-300); text-transform: uppercase; letter-spacing: 0.3px; margin: 0 0 var(--space-4); text-align: center; }
/* Two centered rows, same line-break rule as .boom-builder__payments-row
   (ceil(count/2) chips per row, built server-side — front-page.php) — the
   "formas de pagamento" label above isn't part of this, unlike "pague com:"
   which shares its row with the first chip, so only .boom-footer-trust__payments-row
   itself needs the centering, not a wrapping label alongside it. */
.boom-footer-trust__payments-list { display: flex; flex-direction: column; gap: var(--space-3); }
.boom-footer-trust__payments-row { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--space-3); }
.boom-footer-trust__payment-chip {
	display: inline-flex; align-items: center; gap: var(--space-2);
	background: rgba(255, 255, 255, 0.06);
	border-radius: var(--radius-sm);
	padding: var(--space-3) var(--space-4);
	font-size: 8px; font-weight: var(--weight-semibold); color: #fff;
}
.boom-footer-trust__payment-chip i { color: #fff; }

.boom-footer-trust__links {
	display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-5);
	padding-top: var(--space-5);
	border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.boom-footer-trust__links a { font-size: var(--text-2xs); color: var(--violet-300); text-decoration: underline; }

/* "não achei o serviço" lead-capture popup — same centered-modal/.is-open/
   shared-backdrop convention as .boom-avaliacao-popup (light surface, violet
   top-border accent), whose form/success two-state layout this also mirrors
   (data-boom-servico-form / data-boom-servico-success[hidden]). Shares
   .boom-popup-backdrop via initPopupBackdrop's anyDialogOpen() check (see
   boom.js) — that function needs a matching .boom-servico-popup.is-open check
   added alongside .boom-avaliacao-popup's. */
.boom-servico-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	max-height: min(620px, calc(100% - 2 * var(--page-margin)));
	overflow-y: auto;
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl);
	border-top: 4px solid var(--color-text-brand-deep);
	padding: var(--space-8);
	box-sizing: border-box;
	box-shadow: var(--shadow-xl);
}
.boom-servico-popup.is-open { display: block; }
.boom-servico-popup__close {
	position: absolute; top: var(--space-4); right: var(--space-4);
	width: 24px; height: 24px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	border: none; padding: 0; cursor: pointer;
}
.boom-servico-popup__close i { font-size: 16.9px; }
.boom-servico-popup__head { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-2); padding-right: var(--space-9); }
.boom-servico-popup__head i { font-size: 22.1px; color: var(--color-text-brand-deep); }
.boom-servico-popup__title { font: var(--weight-bold) var(--text-md) var(--font-body); color: var(--color-text-brand-deep); margin: 0; }
.boom-servico-popup__sub { font-size: var(--text-xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0 0 var(--space-7); }
.boom-servico-popup__input {
	display: block; width: 100%; box-sizing: border-box;
	background: var(--color-bg-surface-violet-50);
	border: 2px solid transparent; border-radius: var(--radius-sm);
	padding: var(--space-5) var(--space-6);
	font-size: var(--text-sm); font-family: inherit; color: var(--color-text-primary);
	margin-bottom: var(--space-4);
}
.boom-servico-popup__input.is-invalid { border-color: #FCA5A5; }
.boom-servico-popup__textarea {
	width: 100%; box-sizing: border-box;
	background: var(--color-bg-surface-violet-50);
	border: none; border-radius: var(--radius-sm);
	padding: var(--space-10) var(--space-6);
	padding-top: var(--space-6);
	font-size: var(--text-sm); font-family: inherit;
	resize: none;
	margin-bottom: var(--space-4);
}
.boom-servico-popup__error {
	font-size: var(--text-2xs); color: var(--color-text-warning);
	margin: calc(var(--space-4) * -1) 0 var(--space-6);
}
.boom-servico-popup__submit {
	display: block; width: 100%;
	background: var(--color-bg-cta); color: #fff;
	border: none; border-radius: var(--radius-md);
	padding: var(--space-6); box-sizing: border-box;
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	text-align: center; cursor: pointer;
	margin-bottom: var(--space-4);
}
.boom-servico-popup__submit:hover { filter: brightness(1.05); color: #fff; }
.boom-servico-popup__submit:disabled { opacity: 0.6; cursor: default; }
.boom-servico-popup__consent { font-size: 8px; color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0; }
/* Light-surface override for the reused .boom-order-picker__footer-back
   pill (its own default colors are white-on-dark, for that popup family's
   fixed-dark surface — invisible against this popup's white background). */
.boom-servico-popup__back { margin-top: var(--space-6); border-color: var(--color-border-default); }
.boom-servico-popup__back i,
.boom-servico-popup__back span { color: var(--color-text-brand-deep); }
/* [hidden] and this class share specificity (0,1,0 each) — same gotcha already
   documented on .boom-avaliacao-popup__pending/__success. */
.boom-servico-popup__success[hidden] { display: none; }
.boom-servico-popup__success {
	display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-4);
	padding: var(--space-5) 0 var(--space-2);
}
.boom-servico-popup__success-icon {
	width: 40px; height: 40px;
	border-radius: 50%;
	background: var(--green-100);
	display: flex; align-items: center; justify-content: center;
}
.boom-servico-popup__success-icon i { font-size: 26px; color: var(--green-700); }
.boom-servico-popup__success-title { font: var(--weight-bold) var(--text-base) var(--font-body); color: var(--color-text-primary); margin: 0; }
.boom-servico-popup__success-sub { font-size: var(--text-xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0; }
/* Same purple-CTA treatment as .boom-servico-popup__submit — this button had no
   rule of its own (a leftover from when the success view reused .__submit's
   class), so it was rendering as a bare unstyled <button>. */
.boom-servico-popup__dismiss {
	display: block; width: 100%;
	background: var(--color-bg-cta); color: #fff;
	border: none; border-radius: var(--radius-md);
	padding: var(--space-6); box-sizing: border-box;
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	text-align: center; cursor: pointer;
	margin-top: var(--space-2);
}
.boom-servico-popup__dismiss:hover { filter: brightness(1.05); color: #fff; }
.boom-servico-popup__input,
.boom-servico-popup__textarea { font-size: 16px; }
/* Placeholder-only: the 16px above is an iOS zoom-guard floor for the
   real input (see .boom-checkout-login-popup__input's identical rule),
   not the intended visual size -- restores the field's own declared
   --text-sm for the placeholder, which doesn't affect iOS's zoom trigger. */
.boom-servico-popup__input::placeholder,
.boom-servico-popup__textarea::placeholder { font-size: var(--text-sm); }


/* International phone input (flag + dial code) — boom-core's international-phone-input
   module supplies country data + IP-resolved default country server-side; this is the
   picker UI (boom.js's initPhoneInput()). First used inside .boom-assinatura__open's dark
   card, built as a standalone reusable component (see the TODO to reuse it at checkout).
   Country button + number input share the same .boom-assinatura__input sizing so they read
   as one field row; the dropdown panel reuses the "fixed dark surface" convention already
   established by .boom-combobox__panel (not a token — a deliberate always-dark surface). */
.boom-phone-input {
	position: relative;
	display: flex;
	align-items: stretch;
	gap: var(--space-3);
	margin-bottom: var(--space-4);
}
.boom-phone-input .boom-phone-input__number {
	flex: 1;
	margin-bottom: 0;
	min-width: 0;
}
.boom-phone-input__country {
	flex-shrink: 0;
	display: flex;
	align-items: center;
	gap: var(--space-2);
	background: var(--color-bg-surface-violet-50);
	border: 2px solid transparent;
	border-radius: var(--radius-sm);
	padding: var(--space-4) var(--space-4);
	font-size: var(--text-2xs);
	font-family: inherit;
	color: var(--color-text-primary);
	cursor: pointer;
	white-space: nowrap;
}
.boom-phone-input__country:hover { filter: brightness(0.98); }
/* Chevron affordance -- same recipe as .boom-faq__question's expand icon
   (font-size, color, rotate-on-open transition) so this reads as the same
   kind of "tap to select" control the rest of the site already uses. */
.boom-phone-input__country i { flex-shrink: 0; font-size: 11px; color: var(--color-text-secondary); transition: transform var(--duration-base) var(--ease-standard); }
.boom-phone-input__country.is-open i { transform: rotate(180deg); color: var(--color-text-brand-deep); }

/* position:fixed (not absolute, as this was until 2026-07-19), positioned
   via boom.js's positionPhonePanel() from the country button's own
   getBoundingClientRect() — same reasoning .boom-combobox__panel already
   uses fixed positioning for: an absolutely-positioned panel is clipped by
   any scrollable ancestor's overflow, and .boom-phone-input lives inside
   .boom-assinatura-popup/.boom-servico-popup, both of which scroll. The old
   absolute+"open upward inside the assinatura popup" approach just moved
   the clipping problem from the bottom edge to the top edge instead of
   fixing it — confirmed on a real iPhone: the panel's own top (its first
   row, "Brasil") got clipped by the popup's own scroll boundary the moment
   the trigger sat close enough to the popup's top that the upward-opened
   panel ran out of room above it. Fixed positioning escapes that ancestor
   clipping entirely, and boom.js now picks open-up-vs-open-down (and caps
   the inner list's height to whatever space is actually available) per
   open(), instead of a single CSS rule assuming one direction always fits. */
.boom-phone-input__panel {
	position: fixed;
	z-index: 143;
	width: min(300px, 100%);
	background: linear-gradient(155deg, #3B2F5C, #1F1B2E);
	border-radius: var(--radius-md);
	box-shadow: 0 20px 50px rgba(0, 0, 0, 0.4);
	padding: var(--space-4);
	box-sizing: border-box;
}
/* [hidden] and this component's own display:flex/flex-column rule share specificity
   (0,1,0 each) — same gotcha already documented on .boom-avaliacao-popup__pending and
   .boom-assinatura__submitted, so an explicit override is needed here too. */
.boom-phone-input__panel[hidden] { display: none; }
.boom-phone-input__search {
	display: block;
	width: 100%;
	box-sizing: border-box;
	background: rgba(255, 255, 255, 0.08);
	border: none;
	border-radius: var(--radius-sm);
	padding: var(--space-3) var(--space-4);
	font-size: var(--text-2xs);
	font-family: inherit;
	color: #fff;
	margin-bottom: var(--space-3);
}
.boom-phone-input__search::placeholder { color: rgba(255, 255, 255, 0.5); }
.boom-phone-input__list {
	/* 260px is the pre-2026-07-19 fallback for the instant between the panel
	   becoming visible and positionPhonePanel() setting a real inline
	   max-height — boom.js always sets an inline value once there's a real
	   button rect to measure, which wins over this. */
	max-height: 260px;
	overflow-y: auto;
}
.boom-phone-input__option {
	display: flex;
	align-items: center;
	gap: var(--space-4);
	width: 100%;
	background: none;
	border: none;
	border-radius: var(--radius-sm);
	padding: var(--space-4);
	font-size: var(--text-xs);
	font-family: inherit;
	color: #fff;
	text-align: left;
	cursor: pointer;
}
.boom-phone-input__option:hover { background: rgba(255, 255, 255, 0.08); }
.boom-phone-input__option-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.boom-phone-input__option-dial { color: #C4B5FD; flex-shrink: 0; }

/* ---------- Checkout's WhatsApp field: boom-core's own picker ----------
   2026-07-21 — replaces wcipi-plugin (third-party "WooCommerce
   international phone input") entirely on #billing_phone; see CLAUDE.md's
   "always use boom-core's phone picker, never a third-party one" rule and
   explanation.md §96. The wrap below is BOTH .boom-field__input-wrap
   (this page's light-pill field chrome, defined further down this file)
   and .boom-phone-input (the picker's own wrapper, defined above) — same
   element, two classes. Most of .boom-phone-input's dark-popup-context
   defaults already lose the cascade to .boom-field__input-wrap's own
   rules for free (both single-class selectors, .boom-field__input-wrap
   simply comes later in this file) — only the stray margin-bottom (meant
   for spacing rows *inside* a popup, not relevant here) and the country
   button's own dark-surface background (wrong context on a light field)
   need an explicit reset. The dropdown PANEL itself needs no new CSS at
   all — .boom-phone-input__panel above already is the dark-violet-
   gradient/search-box look this field should have, for free, since it's
   the exact same real component now instead of a third-party lookalike. */
.boom-field__input-wrap.boom-phone-input { margin-bottom: 0; }
.boom-field__input-wrap.boom-phone-input .boom-phone-input__country {
	background: none;
	border: none;
	border-right: var(--border-hairline);
	padding: 0 var(--space-3) 0 0;
	flex-shrink: 0;
	font-size: var(--text-2xs);
	color: var(--color-text-primary);
}

/* iOS Safari auto-zooms the whole page on focus of any text input/select/textarea whose
   computed font-size is under 16px — and (unlike pinch-zoom) ignores the viewport meta
   tag's maximum-scale/user-scalable for this specific case, so the only real fix is to
   float these real, focusable text-entry controls up to 16px. Scoped to actual
   input/textarea/select elements only — buttons, comboboxes and other non-editable
   controls are unaffected and keep the smaller design-system type scale. */
.boom-builder-form select.field,
.boom-builder-form .service_link > .field,
.boom-builder-form .service_comments > .field,
.boom-builder-form .opcao_voto > .field,
.boom-builder-form .service_datetime_picker .field,
.boom-assinatura__input,
.boom-phone-input__search,
.boom-avaliacao-popup__textarea {
	font-size: var(--text-xs);
}

/* ==========================================================================
   Cart + Checkout (combined single-page) — page-finalizar-compra.php,
   woocommerce/cart/cart.php, woocommerce/checkout/*.php overrides.
   WooCommerce's own default stylesheets are dequeued (functions.php,
   woocommerce_enqueue_styles filter) so everything here is the only styling
   these pages get — same "no page-builder/parent styles" approach as the
   rest of the theme.
   ========================================================================== */

/* ---------- Section head (icon-badge + eyebrow label) ----------
   Same visual pattern as .boom-confia__badge/.boom-cashboom__badge
   (24px badge, --radius-sm, tint background, brand-colored icon) applied
   generically for the cart/checkout section headers ("itens da compra",
   "informe seus dados", "forma de pagamento"). */
.boom-checkout-head {
	display: flex;
	align-items: center;
	gap: var(--space-5);
	background: var(--color-bg-surface-violet-50);
	border-radius: var(--radius-md);
	padding: var(--space-5) var(--space-7);
	margin: var(--space-9) 0 var(--space-6);
}
.boom-checkout-cart .boom-checkout-head { margin-top: var(--space-8); }
/* 2026-07-21: head pill now nests INSIDE its card (mockup draws one
   continuous box, not a label floating above a separate box) — kill the
   top margin when it's the box's first child, since .boom-card's own
   padding already creates that space; keep the bottom margin so there's
   still a gap before the card's real content. .boom-checkout-fields is a
   flex column with its own `gap`, which would double up with that bottom
   margin, so it gets zeroed there specifically (higher specificity wins). */
.boom-card > .boom-checkout-head:first-child { margin: 0 0 var(--space-6); }
.boom-checkout-fields > .boom-checkout-head:first-child { margin-bottom: 0; }
.boom-checkout-head__badge {
	width: 24px; height: 24px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface);
	display: inline-flex; align-items: center; justify-content: center;
	box-shadow: var(--shadow-xs);
	flex-shrink: 0;
}
.boom-checkout-head__badge i { font-size: 14.3px; color: var(--color-text-brand); }
.boom-checkout-head__title {
	font: var(--font-eyebrow);
	text-transform: uppercase;
	letter-spacing: var(--tracking-eyebrow);
	color: var(--color-text-brand-deep);
}

/* ---------- Cart list ---------- */
.boom-cart-empty { text-align: center; color: var(--color-text-secondary); font-size: var(--text-sm); }
.boom-cart-empty a { color: var(--color-text-brand); font-weight: var(--weight-semibold); }

.boom-cart-item {
	display: flex;
	gap: var(--space-6);
	padding: var(--space-7) 0;
	border-bottom: var(--border-hairline);
	position: relative;
}
.boom-cart-item:last-of-type { border-bottom: none; }
.boom-cart-item__icon {
	width: 40px; height: 40px;
	border-radius: var(--radius-md);
	background: linear-gradient(155deg, var(--violet-50), var(--violet-100));
	border: var(--border-hairline);
	display: flex; align-items: center; justify-content: center;
	flex-shrink: 0;
}
.boom-cart-item__thumb {
	width: 40px; height: 40px;
	border-radius: var(--radius-md);
	background: var(--ink-900);
	border: var(--border-hairline);
	display: flex; align-items: center; justify-content: center;
	position: relative; flex-shrink: 0; overflow: hidden;
	padding: 0; cursor: pointer;
}
.boom-cart-item__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.boom-cart-item__thumb-zoom {
	position: absolute; top: 2px; left: 2px;
	width: 13px; height: 13px; border-radius: 50%;
	background: rgba(255, 255, 255, 0.9);
	display: flex; align-items: center; justify-content: center;
}
.boom-cart-item__thumb-zoom i { font-size: 8px; color: var(--ink-900); }
.boom-cart-item__media { display: flex; flex-direction: column; align-items: center; justify-content: space-between; flex-shrink: 0; }
.boom-cart-item__body { flex: 1; min-width: 0; }
.boom-cart-item__row { display: flex; align-items: flex-start; gap: var(--space-6); }
.boom-cart-item__title { font: var(--font-label); color: var(--color-text-primary); line-height: var(--leading-normal); display: flex; align-items: center; gap: var(--space-3); }
.boom-cart-item__title i { color: var(--color-text-brand); font-size: 12px; flex-shrink: 0; }
.boom-cart-item__price { font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--color-text-primary); flex-shrink: 0; white-space: nowrap; }
/* Price-wrap: pre-discount price (struck, smaller) and the actual charged
   price (bold, larger) sit on one line, original on the left — the two
   font sizes already come from .boom-cart-item__price-original/__price
   themselves, so this rule only needs to lay them out in a row instead of
   the stacked column it used to be. align-items:baseline keeps their text
   aligned despite the size difference; justify-content:flex-end keeps the
   pair right-aligned as a group, same as before. */
.boom-cart-item__price-wrap { display: flex; align-items: baseline; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-2); }
.boom-cart-item__price-original { font-size: var(--text-xs); white-space: nowrap; }
/* Shared "before" treatment — reused as-is for the promotional base
   quantity below, so both "the number before a discount/bonus" reads as
   the same visual idea. */
.boom-cart-item__struck { text-decoration: line-through; color: var(--color-text-muted); font-weight: var(--weight-regular); }
.boom-cart-item__qty { display: flex; flex-direction: column; gap: 2px; margin-top: var(--space-2); }
.boom-cart-item__qty-row { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); }
.boom-cart-item__qty-label { color: var(--color-text-muted); }
/* Plain (no active promo) quantity reads dark+semibold — it's the only
   number on the row, so it should stand out, not fade like a "before"
   price. Once a promo bonus exists, the compound selector below (higher
   specificity than either single class alone) overrides this back down
   to muted+regular, matching item.baseQtyLabel's two states in
   Carrinho e checkout.dc.html. */
.boom-cart-item__qty-value { color: var(--color-text-primary); font-weight: var(--weight-semibold); }
.boom-cart-item__qty-value.boom-cart-item__struck { color: var(--color-text-muted); font-weight: var(--weight-regular); }
.boom-cart-item__qty-value--promo { color: var(--color-text-success); font-weight: var(--weight-bold); }
.boom-cart-item__qty-arrow { color: var(--color-text-muted); }
.boom-cart-item__promo { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2); }
.boom-cart-item__promo i { color: var(--color-text-success); flex-shrink: 0; }
.boom-cart-item__promo span { font-size: var(--text-2xs); font-weight: var(--weight-bold); color: var(--color-text-success); line-height: var(--leading-tight); }
/* 2026-07-23: padding-right hack removed — it existed only to keep this
   row's ellipsis truncation clear of .boom-cart-item__actions, which used
   to float over this corner via position:absolute. Actions now lives in
   .boom-cart-item__media, alongside the thumbnail, nowhere near this row,
   so there's no more overlap to guard against. */
.boom-cart-item__link {
	display: flex; align-items: center; gap: var(--space-2);
	margin-top: var(--space-2);
	font-size: var(--text-xs); color: var(--color-text-muted);
}
.boom-cart-item__link i { color: var(--ink-400); flex-shrink: 0; }
.boom-cart-item__link a { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: inherit; text-decoration: none; }
.boom-cart-item__link a:hover { text-decoration: underline; }
.boom-cart-item__actions { flex-shrink: 0; }
.boom-cart-item__remove {
	display: inline-flex; align-items: center; justify-content: center;
	width: 26px; height: 26px;
	color: var(--ink-400);
	font-size: 15.6px;
}
.boom-cart-item__remove:hover { color: var(--color-accent-pink); }

/* ---------- Totals (real <table>, styled as flex rows so CashBOOM's
   tr.order-total selector + WooCommerce's own cart_totals class keep
   working exactly as the stock template expects) ---------- */
.boom-cart-totals { width: 100%; border-collapse: collapse; margin-top: var(--space-2); }
.boom-cart-totals tr { display: flex; align-items: center; justify-content: space-between; padding-top: var(--space-7); }
.boom-cart-totals th, .boom-cart-totals td { border: none; padding: 0; font: inherit; text-align: left; font-weight: var(--weight-regular); }
.boom-cart-totals .cart-subtotal th, .boom-cart-totals .cart-subtotal td { font-size: var(--text-xs); color: var(--color-text-secondary); }
.boom-cart-totals .cart-discount th, .boom-cart-totals .cart-discount td { font-size: var(--text-xs); }
.boom-cart-totals .cart-discount th { display: flex; align-items: center; gap: var(--space-4); color: var(--color-text-secondary); }
.boom-cart-totals .cart-discount td { color: var(--color-accent-pink); font-weight: var(--weight-semibold); }
.boom-cart-totals__remove-coupon { font-size: 8.75px; color: var(--ink-400); text-decoration: underline; }
.boom-cart-totals .order-total {
	border-top: var(--border-hairline);
	margin-top: var(--space-6);
	padding-top: var(--space-7);
}
.boom-cart-totals .order-total th { font-size: var(--text-sm); font-weight: var(--weight-bold); color: var(--color-text-primary); }
.boom-cart-totals .order-total td { font-size: var(--text-md); font-weight: var(--weight-bold); color: var(--color-text-brand-deep); }

/* ---------- "resumo do pedido" (form-checkout.php) — .boom-cart-totals
   above supplies the table styling; this only adds the savings badge. ---------- */
/* Card-to-card gap (2026-07-21) — matches the same --space-10 rhythm as
   .boom-payment-box's margin-top and the cart-to-cashboom/cashboom-to-fields
   gaps below, so every card-to-card transition on this page is consistent
   (the mockup's own 12px here was inconsistent with its other gaps). */
.boom-order-summary { margin-top: var(--space-10); }

/* ---------- Coupon ---------- */
.boom-coupon-row { margin-top: var(--space-7); padding-top: var(--space-7); border-top: var(--border-hairline); }
.boom-coupon-row__label { font-size: var(--text-xs); color: var(--color-text-secondary); margin-bottom: var(--space-4); }
.boom-coupon-row__form { display: flex; gap: var(--space-4); }
.boom-coupon-row__input-wrap { position: relative; flex: 1; min-width: 0; }
/* !important needed here: WooCommerce core's own cart styles target
   `.woocommerce-page .woocommerce-cart-form #coupon_code` — an ID
   selector, which beats any class-only override regardless of how many
   classes are chained (same reasoning as the other !important uses in
   this file, all overriding stronger-than-class specificity). */
.boom-coupon-row__input-wrap .boom-field__input { margin: 0 !important; padding-left: var(--space-12) !important; }
.boom-coupon-row__icon {
	position: absolute; left: var(--space-6); top: 50%; transform: translateY(-50%);
	font-size: 13px; color: var(--color-text-muted);
	pointer-events: none;
}
.boom-coupon-row__apply {
	flex-shrink: 0;
	background: var(--color-bg-surface);
	color: var(--color-text-brand);
	border: 1.5px solid var(--color-border-brand);
	border-radius: var(--radius-md);
	padding: var(--space-6) var(--space-8);
	font-size: var(--text-xs); font-weight: var(--weight-bold);
}
.boom-coupon-row__apply:hover { background: var(--color-bg-surface-violet-50); }
/* Touch-target + narrow-viewport fix (2026-07-21) — the input+button row
   held up fine at the 360px mockup width but cramped/overflowed on
   Safari's smallest real viewport (~320px, e.g. iPhone SE). Below 360px,
   stack input and button instead of forcing them side by side; both keep
   a 44px minimum height at every width (WCAG/Material touch-target
   minimum) regardless of stacked/inline layout. */
.boom-coupon-row__input-wrap .boom-field__input,
.boom-coupon-row__apply { min-height: 44px; box-sizing: border-box; }
@media (max-width: 359px) {
	.boom-coupon-row__form { flex-direction: column; }
	.boom-coupon-row__apply { width: 100%; }
}
.woocommerce-message, .woocommerce-error, .woocommerce-info {
	list-style: none; margin: var(--space-6) 0 0; padding: var(--space-5) var(--space-6);
	background: var(--color-bg-surface-tint); border-radius: var(--radius-md);
	font-size: var(--text-xs); color: var(--color-text-primary);
}
.woocommerce-error { background: #FEF2F2; color: #991B1B; }

/* ---------- Checkout fields ("informe seus dados") ---------- */
.boom-checkout-fields { display: flex; flex-direction: column; gap: var(--space-6); }
/* "já é cliente?" quick-login prompt (form-checkout.php, only rendered for
   guests) — same --checkout-blue-* palette as the cashboom banner/conta de
   acesso/link-preview popup. A real link to My Account, not a stub. */
.boom-already-client {
	display: flex; align-items: center; gap: var(--space-5);
	width: 100%;
	background: var(--color-bg-checkout-info);
	border: 1px solid var(--color-icon-checkout-info);
	border-radius: var(--radius-md);
	padding: var(--space-5) var(--space-6);
	text-decoration: none;
	/* Was a real <a> until 2026-07-21 (now a <button> opening the login
	   popup, see initCheckoutLoginPopup() in boom.js) — font/cursor/
	   text-align reset for the browser's own default button chrome;
	   background/border above already fully override the rest. */
	font: inherit;
	text-align: left;
	cursor: pointer;
}
.boom-already-client__icon {
	width: 24px; height: 24px; flex-shrink: 0;
	border-radius: var(--radius-pill);
	background: var(--color-icon-checkout-info);
	display: flex; align-items: center; justify-content: center;
}
.boom-already-client__icon i { font-size: 14px; color: #fff; }
.boom-already-client__text { font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--color-text-checkout-info); line-height: var(--leading-relaxed); }
.boom-already-client__link { text-decoration: underline; font-weight: var(--weight-bold); }

/* ---------- Checkout login popup ----------
   Same recipe as .boom-servico-popup above (centered fixed light card,
   violet-tinted borderless inputs, brand-CTA submit) — parallel, independent
   classes rather than sharing that popup's own, same as every other popup
   pair in this file (e.g. .boom-servico-popup vs .boom-assinatura-popup
   already duplicate this exact pattern independently). Registered in
   initPopupBackdrop()'s cardPopupClasses list (boom.js). */
.boom-checkout-login-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	max-height: min(620px, calc(100% - 2 * var(--page-margin)));
	overflow-y: auto;
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl);
	border-top: 4px solid var(--color-text-brand-deep);
	padding: var(--space-8);
	box-sizing: border-box;
	box-shadow: var(--shadow-xl);
}
.boom-checkout-login-popup.is-open { display: block; }
.boom-checkout-login-popup__close {
	position: absolute; top: var(--space-4); right: var(--space-4);
	width: 24px; height: 24px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	border: none; padding: 0; cursor: pointer;
}
.boom-checkout-login-popup__close i { font-size: 16.9px; }
.boom-checkout-login-popup__head { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-2); padding-right: var(--space-9); }
.boom-checkout-login-popup__head i { font-size: 22.1px; color: var(--color-text-brand-deep); }
.boom-checkout-login-popup__title { font: var(--weight-bold) var(--text-md) var(--font-body); color: var(--color-text-brand-deep); margin: 0; }
.boom-checkout-login-popup__sub { font-size: var(--text-xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0 0 var(--space-7); }
.boom-checkout-login-popup__input {
	display: block; width: 100%; box-sizing: border-box;
	background: var(--color-bg-surface-violet-50);
	border: 2px solid transparent; border-radius: var(--radius-sm);
	padding: var(--space-5) var(--space-6);
	font-size: var(--text-sm); font-family: inherit; color: var(--color-text-primary);
	margin-bottom: var(--space-4);
}
/* margin-bottom moved from the input onto the wrap (input's own is zeroed
   here) so the wrap's rendered height is exactly the input's own height,
   with nothing inside it for the toggle button's top:50% to misjudge —
   avoids depending on margin-collapse behavior at the wrap's bottom edge. */
.boom-checkout-login-popup__password-wrap { position: relative; margin-bottom: var(--space-4); }
.boom-checkout-login-popup__password-wrap .boom-checkout-login-popup__input { margin-bottom: 0; padding-right: var(--space-11); }
.boom-checkout-login-popup__toggle-password {
	position: absolute; top: 50%; right: var(--space-5); transform: translateY(-50%);
	background: none; border: none; padding: var(--space-2); cursor: pointer;
	color: var(--color-text-secondary);
	display: flex; align-items: center;
}
.boom-checkout-login-popup__error { font-size: var(--text-2xs); color: var(--color-text-warning); margin: calc(var(--space-4) * -1) 0 var(--space-6); }
.boom-checkout-login-popup__submit {
	display: block; width: 100%;
	background: var(--color-bg-cta); color: #fff;
	border: none; border-radius: var(--radius-md);
	padding: var(--space-6); box-sizing: border-box;
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	text-align: center; cursor: pointer;
	margin-bottom: var(--space-5);
}
.boom-checkout-login-popup__submit:hover { filter: brightness(1.05); color: #fff; }
.boom-checkout-login-popup__submit:disabled { opacity: 0.6; cursor: default; }
/* .__forgot ("esqueci minha senha") and .__back ("voltar pro login") share
   this look — both are real <button>s now (2026-07-21: .__forgot used to
   be a plain <a> navigating to wp_lostpassword_url(), see boom.js's
   initCheckoutLoginPopup() for why that changed), so both get the same
   browser-button-chrome reset plus the original link-style appearance. */
.boom-checkout-login-popup__forgot,
.boom-checkout-login-popup__back {
	display: block; width: 100%;
	background: none; border: none; padding: 0;
	text-align: center; cursor: pointer;
	font: inherit; font-size: var(--text-2xs); color: var(--color-text-secondary);
	text-decoration: underline;
}
/* "ainda não tem conta? · criar conta" (login view) — a plain secondary
   line + a bold underlined accent link, inline. Same row shape as the
   mockup's own signup-hint row (Boom Home.dc.html), just using this
   project's real design-system tokens instead of the mockup's raw hex. */
.boom-checkout-login-popup__signup-hint {
	display: flex; align-items: center; justify-content: center; gap: var(--space-2);
	margin-top: var(--space-5);
	font-size: var(--text-2xs); color: var(--color-text-secondary);
}
.boom-checkout-login-popup__signup-hint button {
	background: none; border: none; padding: 0;
	font: inherit; font-weight: var(--weight-bold);
	color: var(--color-text-brand-deep);
	text-decoration: underline;
	cursor: pointer;
}
/* Small supplementary line under a field (register view's whatsapp/senha
   hints) — same negative-margin-pull-up + bottom-gap shape as .__error
   above, just muted instead of warning-colored since these aren't errors. */
.boom-checkout-login-popup__hint {
	font-size: var(--text-2xs); color: var(--color-text-secondary);
	line-height: var(--leading-relaxed);
	margin: calc(var(--space-4) * -1) 0 var(--space-6);
}
/* iOS zoom guard (same reasoning as .boom-servico-popup__input's own
   identical rule) — scoped to the real inputs only, not the forgot/back
   buttons, which aren't focusable text-entry controls. */
.boom-checkout-login-popup__input { font-size: 16px; }
/* Success view (boom_ajax_checkout_forgot_password() succeeded) — same
   green-check-circle recipe as .boom-servico-popup__success-icon. */
.boom-checkout-login-popup__success {
	display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-4);
	padding: var(--space-2) 0 var(--space-6);
}
.boom-checkout-login-popup__success-icon {
	width: 40px; height: 40px;
	border-radius: 50%;
	background: var(--green-100);
	display: flex; align-items: center; justify-content: center;
}
.boom-checkout-login-popup__success-icon i { font-size: 26px; color: var(--green-700); }
.boom-checkout-login-popup__success .boom-checkout-login-popup__title,
.boom-checkout-login-popup__success .boom-checkout-login-popup__sub { margin: 0; }

/* ---------- Hamburger "menu sheet" ----------
   Bottom-drawer shortcut list (footer.php, opened by the bottom nav's
   hamburger — mobile bar and, reflowed, the desktop sidebar, same element
   either way). Same theme-owned/.is-open/shared-backdrop convention as
   .boom-checkout-login-popup above (registered in initPopupBackdrop()'s
   cardPopupClasses list, boom.js) but bottom-anchored instead of centered,
   matching the mockup's own bottom-sheet treatment for this one popup. */
.boom-menu-sheet {
	display: none;
	position: fixed; z-index: 91;
	left: 50%; bottom: 0; transform: translateX(-50%);
	width: 100%; max-width: 448px;
	max-height: 80vh;
	overflow-y: auto;
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl) var(--radius-xl) 0 0;
	padding: var(--space-6) var(--space-6) var(--space-9);
	box-sizing: border-box;
	box-shadow: var(--shadow-xl);
}
.boom-menu-sheet.is-open { display: block; }
.boom-menu-sheet__close {
	position: absolute; top: var(--space-4); right: var(--space-4);
	width: 24px; height: 24px;
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: var(--radius-pill);
	background: none; border: none;
	color: var(--color-text-secondary);
}
.boom-menu-sheet__handle { width: 34px; height: 4px; background: var(--color-bg-surface-tint); border-radius: 2px; margin: 2px auto var(--space-6); }
.boom-menu-sheet__item {
	display: flex; align-items: center; gap: var(--space-5);
	padding: var(--space-6) var(--space-5);
	border-radius: var(--radius-md);
	color: var(--color-text-primary);
	text-decoration: none;
}
.boom-menu-sheet__item:hover { background: var(--color-bg-surface-tint); color: var(--color-text-primary); }
.boom-menu-sheet__item i { font-size: 17px; color: var(--color-text-brand); flex-shrink: 0; }
.boom-menu-sheet__item span { font-size: var(--text-sm); font-weight: var(--weight-medium); }

/* ---------- Checkout loading overlay ----------
   Rendered with .is-open already present in the markup (page-finalizar-
   compra.php), unlike every other popup here — it has to cover the very
   first paint, not just a later click. Shares .boom-popup-backdrop via
   initPopupBackdrop()'s anyDialogOpen() check (boom.js), same as
   .boom-checkout-login-popup above, so the dim/blur + scroll-lock behave
   identically; boom.js's initCheckoutLoadingOverlay() removes is-open once
   WooCommerce's first update_order_review AJAX call resolves. No close
   button on purpose — this isn't a user-dismissible dialog. */
.boom-checkout-loading {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl);
	border-top: 5px solid var(--color-text-brand-deep);
	padding: var(--space-8) var(--space-10);
	box-shadow: var(--shadow-xl);
	/* Bumped from --text-sm (13.65px) 2026-07-25 - was under the 16px
	   mobile-readable-body-text floor (ui-ux-pro-max skill, "Readable Font
	   Size", High severity) and read as too small on a real device. */
	font: var(--weight-bold) var(--text-lg) var(--font-body);
	color: var(--color-text-brand-deep);
	white-space: nowrap;
}
.boom-checkout-loading.is-open { display: block; }
/* Reserves width for the longest dot state ("...") so the box doesn't
   jiggle horizontally as initCheckoutLoadingOverlay() cycles the dots —
   functional motion (a real loading indicator), not the decorative looping
   animation tokens.css's Motion section rules out. */
.boom-checkout-loading__dots { display: inline-block; width: 1.2em; text-align: left; }

/* ---------- "Monte seu pedido" loading overlay ----------
   Same "Carregando..." + animated-dots idea as .boom-checkout-loading
   above, but scoped locally to #servicos/.boom-builder-form (position:
   absolute over just this box) instead of the whole page — the rest of
   the home page stays usable while boom-core's own loadLevels() AJAX
   (home.js) populates #cat. Rendered already .is-open (page markup),
   boom.js's initOrderBuilderLoadingOverlay() removes it once #cat is no
   longer disabled. No shared .boom-popup-backdrop here on purpose — this
   isn't a full-page dialog, so it doesn't lock body scroll either. */
.boom-builder-form { position: relative; }
.boom-builder-loading {
	display: none;
	position: absolute; inset: 0; z-index: 5;
	align-items: center; justify-content: center;
	background: rgba(255, 255, 255, 0.92);
	font: var(--weight-bold) var(--text-sm) var(--font-body);
	color: var(--color-text-brand-deep);
}
.boom-builder-loading.is-open { display: flex; }
.boom-builder-loading__dots { display: inline-block; width: 1.2em; text-align: left; }
.boom-field { display: flex; flex-direction: column; }
.boom-field__label { font-size: var(--text-2xs); font-weight: var(--weight-semibold); color: var(--color-text-primary); margin-bottom: var(--space-3); }
.boom-field__req { font-weight: var(--weight-regular); color: var(--color-text-muted); }
.boom-field__input {
	width: 100%; box-sizing: border-box;
	background: var(--color-bg-surface-tint);
	border: var(--border-hairline);
	border-radius: var(--radius-md);
	padding: var(--space-6) var(--space-6);
	font-size: var(--text-2xs); font-family: inherit; color: var(--color-text-primary);
}
.boom-field__input:focus { outline: none; border-color: var(--color-border-brand); }
.boom-field__input-wrap {
	display: flex; align-items: center; gap: var(--space-5);
	background: var(--color-bg-surface-tint);
	border: var(--border-hairline);
	border-radius: var(--radius-md);
	padding: var(--space-6);
}
.boom-field__input--plain { background: transparent; border: none; padding: 0; flex: 1; min-width: 0; }
.boom-field__input--plain:focus { outline: none; }
/* Checkout error-summary "jump to field" links (initCheckoutErrorNoticeLinks(),
   boom.js) scroll these 3 real, visible fields to the top of the viewport -
   same header-clearance offset as #monte-pedido/#faq elsewhere in this file. */
#billing_first_name,
#billing_phone_number,
#billing_email,
#billing_cpf { scroll-margin-top: 74px; }
.boom-field__hint { display: flex; gap: var(--space-3); align-items: flex-start; margin: var(--space-4) 0 0; font-size: var(--text-2xs); color: var(--color-text-muted); line-height: var(--leading-relaxed); }
.boom-field__hint i { flex-shrink: 0; margin-top: 1px; }
/* Blur+debounce field validation (initCheckoutFieldValidation(), boom.js) —
   same red/warning token .boom-servico-popup__error already uses for the
   same purpose, just applied to this page's light fields instead of that
   popup's dark ones. .is-invalid targets whichever element is this field's
   own visual boundary: .boom-field__input itself for name/email, but the
   whole .boom-field__input-wrap for phone (its own input is borderless/
   transparent — .boom-field__input--plain — so a border on it alone
   wouldn't show). */
.boom-field__input.is-invalid,
.boom-field__input-wrap.is-invalid { border-color: #FCA5A5; }
.boom-field__error { font-size: var(--text-2xs); color: var(--color-text-warning); margin: var(--space-3) 0 0; }

/* ---------- PIX discount banner ---------- */
.boom-pix-discount-banner {
	display: flex; gap: var(--space-6); align-items: center;
	background: linear-gradient(135deg, var(--color-bg-success), var(--color-bg-surface-violet-50));
	border: 0.5px solid var(--color-border-success);
	border-radius: var(--radius-lg);
	padding: var(--space-6) var(--space-7);
	margin-top: var(--space-9);
	box-shadow: var(--shadow-xs);
}
.boom-pix-discount-banner__icon {
	width: 28px; height: 28px; flex-shrink: 0;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface);
	display: flex; align-items: center; justify-content: center;
	box-shadow: var(--shadow-xs);
	color: var(--color-text-success);
}
.boom-pix-discount-banner__title { font-size: var(--text-xs); font-weight: var(--weight-bold); color: var(--color-text-success-deep); }
.boom-pix-discount-banner__sub { font-size: var(--text-2xs); color: var(--green-muted); margin-top: var(--space-2); }

/* ---------- Payment box ---------- */
/* #boom-payment-box-fixed (boom.js's boomRelocatePaymentContent()) has no
   margin of its own by default, so it sat right up against the pix banner
   above it with no gap — mockup's own "forma de pagamento" box has
   margin-top:22px. --space-10 (24px) is the closest token to that. */
.boom-payment-box { border: var(--border-selected); box-shadow: var(--shadow-lg); margin-top: var(--space-10); }
.boom-payment-box__intro { font-size: var(--text-2xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0 0 var(--space-7); }
.boom-payment-methods { list-style: none; margin: 0; padding: 0; }
.boom-payment-method { margin-top: var(--space-5); }
.boom-payment-method:first-child { margin-top: 0; }
.boom-payment-method__row {
	display: flex; align-items: center; gap: var(--space-6);
	border: var(--border-default);
	border-radius: var(--radius-md);
	padding: var(--space-6);
	cursor: pointer;
	transition: box-shadow var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
/* Selected state: the border/tint move to the whole <li> (row + box
   together), not just the row — 2026-07-21 fix. Before, a gateway with
   extra fields (PIX's CPF field, rendered in .boom-payment-method__box
   below the row) visually floated outside/below the "selected" pill
   instead of reading as one connected unit, since only __row had a
   border. Gateways with no extra fields (mercado pago, stripe) still look
   identical either way — box stays empty/hidden for them.
   Driven by :has() against the actual radio's :checked state (not a class
   toggled by JS/server-render) — updates instantly on click, no AJAX
   round-trip or event listener needed. */
.boom-payment-method:has(.boom-payment-method__radio:checked) {
	border: var(--border-selected);
	border-radius: var(--radius-md);
	background: var(--color-bg-surface-violet-50);
	box-shadow: var(--shadow-xs);
	padding: var(--space-3);
}
.boom-payment-method:has(.boom-payment-method__radio:checked) .boom-payment-method__row {
	border: none;
	padding: var(--space-3);
}
.boom-payment-method__radio { width: 16px; height: 16px; accent-color: var(--violet-600); flex-shrink: 0; }
.boom-payment-method__icon { display: inline-flex; color: var(--color-text-primary); flex-shrink: 0; }
.boom-payment-method__label { flex: 1; font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--color-text-primary); text-transform: lowercase; }
.boom-payment-method__label:first-letter { text-transform: uppercase; }
.boom-payment-method__badge {
	font-size: var(--text-2xs); font-weight: var(--weight-bold);
	color: var(--color-text-success); background: var(--color-bg-success);
	padding: var(--space-2) var(--space-4); border-radius: var(--radius-sm);
	flex-shrink: 0;
}
.boom-payment-method__box { padding: var(--space-6) var(--space-3) var(--space-2); }
.boom-payment-method:has(.boom-payment-method__radio:checked) .boom-payment-method__box { padding-left: 0; padding-right: 0; }
.boom-payment-method__box p { font-size: var(--text-2xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); margin: 0 0 var(--space-6); }
/* No top margin of its own — now that the PIX gateway's description
   paragraph is removed (functions.php's boom_remove_pix_gateway_description()),
   the CPF field is .boom-payment-method__box's first real child, so its
   spacing from the row above comes from the box's own padding-top
   (--space-6, matching the site's normal field-to-field rhythm)
   instead of stacking an extra margin on top of that. */
.boom-payment-method__box > .boom-cpf-field:first-child { margin-top: 0; }
.boom-cpf-field { margin-top: var(--space-2); }

/* PIX box cleanup, user-reported 2026-07-28: the generic box padding
   (--space-6/--space-3/--space-2) left too much dead space above/below
   Efi/Gerencianet's own gateway markup, which itself contributes an
   empty gap of its own (see #wc-wc_gerencianet_pix-cc-form below - its
   one real field, #gn_field_pix, is always display:none, hidden by the
   plugin's own scripts-pix.js the instant it detects our #billing_cpf
   field exists, which it always does; only the fieldset's own default
   padding was left rendering that empty space). Scoped to PIX
   specifically, not the shared .boom-payment-method__box rule (line
   4819) - other gateways' boxes are untouched. */
.boom-payment-method__box.payment_method_wc_gerencianet_pix { padding: 0; }
#wc-wc_gerencianet_pix-cc-form { padding: 0; margin: 0; }
/* .woocommerce-page label's site-wide margin-bottom:.7em (WooCommerce
   core's own woocommerce-blocktheme.css, not this theme's - can't edit
   that file directly, it'd be lost on the next WC update) was adding an
   extra gap under the PIX row specifically. Matched via [for=...] rather
   than the shared .boom-payment-method__row class so only PIX's row
   loses it, not every gateway's. */
label.boom-payment-method__row[for="payment_method_wc_gerencianet_pix"] { margin-bottom: 0; }
/* CPF field's own left edge now needs to match the row's own left
   padding directly (space-3) - the box's padding-left is zeroed while
   checked (line 4820, shared by every gateway), so without this the
   field sat space-3 to the left of where the row's content starts. */
.boom-cpf-field { padding-left: var(--space-3); }

/* MercadoPago's own checkout web-component chrome
   (mp-plugins-components.min.css, can't edit that file either) - both
   already !important in the source, so the override needs to match;
   wins on source order since boom.css loads after it. */
.mp-checkout-pro-checkout-benefits { display: none !important; }
.mp-checkout-pro-payment-methods { padding-top: 0 !important; }
/* Same pattern as the two rules above - user-reported 2026-07-28
   follow-up, more of MercadoPago's own checkout-pro chrome. All
   already !important in the source (mp-plugins-components.min.css),
   matched here for the same reason. */
.mp-checkout-pro-redirect { margin-top: 0 !important; }
.mp-checkout-pro-content { padding: 8px 16px 8px !important; }
.mp-payment-methods-v2-title { padding-bottom: 8px !important; }
.mp-payment-methods-v2-list { padding-bottom: 8px !important; }

/* Stripe's "save payment method" checkbox — a bare, class-less <fieldset>
   (woocommerce-gateway-stripe's save_payment_method_checkbox()) wrapping a
   single .woocommerce-SavedPaymentMethods-saveNew <p>. Traced live
   (upe-classic.js's Le()): the <p> only ever gets display:block when the
   shopper is already logged in (or, on stores that offer it, has ticked
   "create account" at checkout — this store doesn't). For every guest
   checkout — the normal case here, since accounts are auto-created at
   order placement, not before — the <p> stays display:none permanently,
   regardless of whether card details are filled in. The bare fieldset
   still carries the browser's default border+padding though, so even with
   its only child hidden, it rendered as an empty bordered box above the
   "pagar" button. Reset via :has() (targets this specific fieldset without
   touching #wc-stripe-upe-form, which now lives in boom-core's own
   payments/stripe/assets/css/) so the hidden state collapses to
   truly nothing; styled to match the site's own field-label rhythm for the
   rare case it *does* render (logged-in customers). */
fieldset:has(> .woocommerce-SavedPaymentMethods-saveNew) { border: 0; margin: 0; padding: 0; }
.woocommerce-SavedPaymentMethods-saveNew {
	display: flex; align-items: flex-start; gap: var(--space-4);
	margin: var(--space-6) 0 0;
}
.woocommerce-SavedPaymentMethods-saveNew input[type="checkbox"] { accent-color: var(--violet-600); flex-shrink: 0; margin-top: 1px; }
.woocommerce-SavedPaymentMethods-saveNew label { font-size: var(--text-2xs); color: var(--color-text-secondary); line-height: var(--leading-relaxed); }

/* boom-core's account-creation notice (#boom-checkout-account-notice,
   checkout-hooks.php render_checkout_notice()). Plain icon + inline text,
   no card background — matches Carrinho e checkout.dc.html's "conta de
   acesso" row exactly (was a boxed card with a separate bold header line
   until 2026-07-21; the mockup never drew a box here). Reuses the same
   --checkout-blue-* tokens as the cashboom banner/link-preview popup icon. */
#boom-checkout-account-notice {
	display: flex; gap: var(--space-4); align-items: flex-start;
	margin-top: var(--space-8);
	font-size: var(--text-2xs); line-height: var(--leading-relaxed);
	color: var(--color-text-checkout-info);
}
#boom-checkout-account-notice i { font-size: 13px; color: var(--color-icon-checkout-info); flex-shrink: 0; margin-top: 1px; }
#boom-checkout-account-notice strong { font-weight: var(--weight-bold); }

.boom-place-order-row { margin-top: var(--space-8); }
/* Amount (::after) is CSS-generated content, not a child element — see
   order-button.php's doc comment: WooCommerce core's own checkout.js
   overwrites #place_order's child nodes via $(...).text() on every
   payment-method change, which pseudo-element content is immune to. It
   participates as a flex item automatically alongside the button's own
   text node, so the gap-based layout below still lines up "pagar" / amount
   exactly as if it were a real child.
   font-family is set explicitly (not just inherited) on purpose: an
   earlier version put icon-font classes on this button for a lock icon,
   and that icon font's own base rule sets font-family with !important on
   the whole element — since font-family is inherited, it silently applied
   to this button's own text too, and the icon webfont has no real
   letter/digit glyphs, so "pagar" and the amount rendered blank in every
   real browser (only a couple of stray codepoints happened to have visible
   fallback glyphs). No icon on this button anymore, but pinning the real
   body font here directly guards against the same class of bug if
   anything else ever adds an icon-font class to this specific element. */
.boom-place-order {
	display: flex; align-items: center; justify-content: center; gap: var(--space-5);
	width: 100%;
	background: var(--color-bg-cta);
	color: #fff; border: none;
	border-radius: var(--radius-md);
	padding: var(--space-7);
	margin-top: var(--space-8);
	font-family: var(--font-body);
	font-size: var(--text-sm); font-weight: var(--weight-bold);
	letter-spacing: 0.2px;
	box-shadow: var(--shadow-button);
	text-transform: lowercase;
}
.boom-place-order:hover { filter: brightness(1.05); color: #fff; }
.boom-place-order.processing { opacity: 0.7; pointer-events: none; }
/* .boom-place-order's own text-transform:lowercase (keeps the "pagar" label
   lowercase regardless of what WC core's checkout.js sets it to) would
   otherwise inherit onto this pseudo-element too, lowercasing the real
   currency symbol ("R$" -> "r$") along with it — excluded here since the
   amount should keep its real casing. */
.boom-place-order::after { content: attr(data-price); text-transform: none; }
.woocommerce-terms-and-conditions-wrapper { margin-top: var(--space-6); font-size: var(--text-2xs); color: var(--color-text-secondary); }
.woocommerce-terms-and-conditions-wrapper a { text-decoration: underline; }

/* Hidden functional scaffolding — required in the DOM (checkout.js AJAX
   target + CashBOOM's tr.order-total read), never shown. See the comment
   in woocommerce/checkout/review-order.php. */
.boom-order-review-sync-inner { display: none; }

/* CashBOOM's own boxes (cashboom-ui.php) dropped into our cart/checkout —
   light restyle so they read as part of the design instead of unstyled
   default text. Blue accent (was pink/violet until the 2026-07-21 mockup
   revision — Carrinho e checkout.dc.html's cashboom banner switched to the
   same --checkout-blue-* palette as the "informe seus dados" login hint and
   the link-preview popup's info icon). */
.cashboom-ui-notice {
	display: block;
	background: var(--color-bg-checkout-info);
	border: 0.5px solid var(--color-border-checkout-info);
	border-radius: var(--radius-lg);
	padding: var(--space-7);
	margin-top: var(--space-10);
	box-shadow: 0 4px 12px rgba(47, 111, 237, 0.06);
}
.cashboom-ui-notice h3 { font-size: var(--text-xs); font-weight: var(--weight-black); color: var(--color-icon-checkout-info); text-transform: uppercase; letter-spacing: 0.4px; margin: 0; }
.cashboom-ui-notice h6 { font-size: 9px; font-weight: var(--weight-semibold); color: var(--color-text-checkout-info); text-transform: uppercase; letter-spacing: 0.3px; margin: var(--space-2) 0 0; }
.cashboom-ui-content { font-size: var(--text-2xs); color: var(--color-text-checkout-info); line-height: var(--leading-relaxed); margin-top: var(--space-4); }
/* "ver regras" trigger (cart context only, added 2026-07-28, moved same day
   from the head row to sit left-aligned below .cashboom-ui-content, and
   recolored to this box's own checkout-blue palette instead of the violet
   brand color copied from .boom-myaccount-cashboom-card__rules-btn -- user
   feedback: the violet text didn't fit this box's blue tint. Shape (bordered
   pill + icon) kept from that reference; only the palette changed. Sits in
   normal block flow now (no more .cashboom-ui-notice__head flex wrapper --
   removed, only ever had 2 possible children and the button is no longer
   one of them) so it naturally lands bottom-left, block-level, no explicit
   alignment rule needed. */
.cashboom-ui-notice__rules-btn {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	margin-top: var(--space-6);
	background: var(--color-bg-surface);
	border: 1px solid var(--color-border-checkout-info);
	border-radius: var(--radius-pill);
	padding: var(--space-3) var(--space-6);
	font-size: 10px;
	font-weight: var(--weight-bold);
	color: var(--color-icon-checkout-info);
	cursor: pointer;
	white-space: nowrap;
}
.cashboom-ui-notice__rules-btn i { font-size: 10px; }
tr.cashboom-ui-row--checkout td { padding: 0; }
tr.cashboom-ui-row--checkout .cashboom-ui-notice { margin-top: var(--space-6); }

/* iOS Safari auto-zoom fix — same rule as the rest of the theme (see
   boom.css's original comment on this selector list): real text inputs
   need 16px, this just extends that list to the new checkout fields. */
.boom-field__input,
.boom-field__input--plain,
#coupon_code {
	font-size: 16px;
}

/* ==================== Order-received / "thank-you" page (thank you.dc.html) ====================
   woocommerce/checkout/thankyou.php + order/order-details(-item).php. */

.boom-order-hero {
	padding: 22px 22px 24px;
	border-radius: 16px;
	position: relative;
	overflow: hidden;
}
.boom-order-hero + .boom-section { margin-top: 18px; }
.boom-order-hero__eyebrow {
	font: var(--weight-bold) 9.5px var(--font-body);
	color: var(--color-text-on-dark-soft);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	margin: 0 0 var(--space-4);
	position: relative;
}
.boom-order-hero__title {
	font: var(--weight-bold) var(--text-xl) var(--font-display);
	color: var(--color-text-on-dark);
	line-height: 1.3;
	margin: 0;
	position: relative;
}
.boom-order-hero__sub {
	font: var(--weight-regular) 9.5px var(--font-body);
	/* thank you.dc.html's own sub color (#b7aedb) is a distinct, slightly
	   more muted lavender than the eyebrow's --violet-300 (#c4b5fd) — no
	   existing token matches it, hardcoded rather than reusing eyebrow's
	   color like the previous version did. */
	color: #b7aedb;
	margin: var(--space-4) 0 0;
	position: relative;
}
/* Giant, near-invisible decorative icon in the card's corner (same
   treatment as home's .boom-hero__rocket-bg, just this card's own smaller
   scale) + an icon badge next to the eyebrow. Both states render these
   now (thank you - Aguardando pagamento.dc.html / thank you -
   Pago.dc.html each have their own icon — clock-hour-4/circle-check for
   the bg icon, clock/check for the badge — swapped per branch in
   thankyou.php, not two separate CSS treatments) — .boom-order-hero__sub
   above needing explicit `position:relative` to sit above the bg icon
   applies to both branches for the same reason. */
.boom-order-hero__bg-icon {
	position: absolute;
	top: -26px;
	right: -26px;
	font-size: 150px;
	color: rgba(255, 255, 255, 0.055);
	pointer-events: none;
	line-height: 1;
}
.boom-order-hero__eyebrow--badged {
	display: flex;
	align-items: center;
	gap: var(--space-5);
}
.boom-order-hero__eyebrow-icon {
	width: 32px;
	height: 32px;
	border-radius: 50%;
	/* Tint of --violet-300 (#c4b5fd) — same "no exact token, hardcode it"
	   precedent as .boom-order-hero__sub above. */
	background: rgba(196, 181, 253, 0.16);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}
.boom-order-hero__eyebrow-icon i { font-size: 17px; color: var(--violet-300); }

/* "avisaremos" notice + 4-step order tracker — both branches render the
   same two cards (thankyou.php's $boom_progress_steps unconditionally set,
   only each step's is-active/is-done state differs). Used to be awaiting-
   only, with a separate plain .boom-order-status-card--success card for the
   paid branch; that card is gone (removed 2026-07-24, synced to thank you -
   Pago.dc.html — see explanation.md), so if a green/plain success-card
   style is ever needed again elsewhere, don't assume this component still
   has one. Split into 2 separate <section>s 2026-07-26 (explanation.md
   §180) so only the step row (.boom-order-progress-card-sticky) sticks
   under .boom-header on scroll — the notice card above it stays in normal
   flow. Square-corner pairing + zero gap between them (the sticky card
   isn't .boom-section, no auto top margin) makes the two read as one
   continuous card until the notice scrolls out from under the sticky one —
   same pattern as page-finalizar-compra.php's .boom-checkout-notice-card/
   .boom-checkout-steps-card. */
.boom-order-notice-card {
	border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.boom-order-progress-card-sticky {
	position: sticky;
	top: var(--boom-header-height, 70.5px); /* live-measured (initStickyHeaderOffset(), boom.js) — same as .boom-checkout-steps-card */
	z-index: 20;
	border-radius: 0 0 var(--radius-lg) var(--radius-lg);
	box-shadow: var(--shadow-sm);
}
.boom-order-progress-card__notice { display: flex; align-items: center; gap: var(--space-6); }
.boom-order-progress-card__notice-icon {
	width: 36px;
	height: 36px;
	border-radius: var(--radius-md);
	background: var(--color-bg-surface-violet-50);
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}
.boom-order-progress-card__notice-icon i { font-size: 18px; color: var(--color-text-brand); }
.boom-order-progress-card__notice-text { flex: 1; min-width: 0; }
.boom-order-progress-card__notice-title {
	font: var(--weight-bold) var(--text-xs) var(--font-body);
	color: var(--color-text-primary);
	line-height: 1.3;
	margin: 0;
}
.boom-order-progress-card__notice-channels {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--space-5);
	margin: var(--space-3) 0 0;
	font-size: var(--text-2xs);
	color: var(--color-text-muted);
}
.boom-order-progress-card__notice-channels span { display: inline-flex; align-items: center; gap: 3px; }
.boom-order-progress-card__notice-channels i { font-size: 12px; }
.boom-order-progress-card__notice-channels span:first-child i { color: #25d366; } /* whatsapp brand green, same as every other whatsapp icon in this file */
.boom-order-progress-card__notice-channels span:last-child i { color: var(--color-text-brand); }

.boom-order-progress {
	display: flex;
	align-items: flex-start;
}
.boom-order-progress__step { display: flex; flex-direction: column; align-items: center; flex: 1; }
.boom-order-progress__circle {
	width: 28px;
	height: 28px;
	border-radius: 50%;
	background: var(--color-bg-surface-tint);
	border: 1.5px solid var(--violet-100);
	display: flex;
	align-items: center;
	justify-content: center;
}
.boom-order-progress__circle i { font-size: 14px; color: var(--color-text-muted); }
/* Same "native icon vs. done checkmark" swap convention as
   .boom-checkout-steps .boom-step.is-done (boom.css, checkout step
   tracker) — each circle renders both icons, CSS shows only one. */
.boom-order-progress__icon--done { display: none; }
.boom-order-progress__step.is-done .boom-order-progress__icon--native { display: none; }
.boom-order-progress__step.is-done .boom-order-progress__icon--done { display: inline; }
.boom-order-progress__step.is-active .boom-order-progress__circle,
.boom-order-progress__step.is-done .boom-order-progress__circle {
	border-color: transparent;
}
.boom-order-progress__step.is-active .boom-order-progress__circle {
	background: var(--amber-500);
	box-shadow: 0 4px 10px rgba(245, 158, 11, 0.30);
}
.boom-order-progress__step.is-active .boom-order-progress__circle i { color: #fff; }
.boom-order-progress__step.is-done .boom-order-progress__circle {
	background: var(--color-text-brand);
	box-shadow: 0 4px 10px rgba(109, 40, 217, 0.28);
}
.boom-order-progress__step.is-done .boom-order-progress__circle i { color: #fff; }
.boom-order-progress__label {
	font: var(--weight-bold) 8.5px var(--font-body);
	color: var(--color-text-primary);
	margin-top: 7px;
	text-align: center;
	line-height: 1.3;
}
.boom-order-progress__step:not(.is-active):not(.is-done) .boom-order-progress__label {
	color: var(--color-text-muted);
	font-weight: var(--weight-semibold);
}
.boom-order-progress__line {
	flex: 1;
	height: 2px;
	background: var(--violet-100);
	margin: 0 4px;
	margin-top: 13px;
	border-radius: 1px;
	transition: background var(--duration-base) var(--ease-standard);
}
.boom-order-progress__line.is-filled { background: var(--color-text-brand); }

/* Unbadged Pix QR/copy card — no "forma de pagamento" framing (removed per
   request), just a slightly emphasized card since it's the one actionable
   thing left for the customer to do. */
.boom-order-pix-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	border: var(--border-selected);
	box-shadow: var(--shadow-md);
}
.boom-order-pix-card .boom-checkout-head { align-self: stretch; }
.boom-order-pix-card__amount-label {
	font: var(--weight-semibold) var(--text-2xs) var(--font-body);
	color: var(--color-text-muted);
	text-transform: uppercase;
	letter-spacing: var(--tracking-eyebrow);
	margin-top: var(--space-2);
}
.boom-order-pix-card__amount {
	font: var(--weight-bold) 30px var(--font-display);
	color: var(--color-text-brand-deep);
	line-height: 1.1;
	margin-top: 2px;
}
.boom-order-pix-card__expiry {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	background: var(--color-bg-warning);
	border: 1px solid var(--color-border-warning);
	border-radius: 999px;
	padding: 5px 11px;
	margin-top: var(--space-5);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	color: var(--color-text-warning);
}
.boom-order-pix-card__expiry i { font-size: 12px; }
.boom-order-pix-card__howto {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin-top: var(--space-6);
	background: none;
	border: none;
	padding: 4px;
	cursor: pointer;
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	color: var(--color-text-brand);
	text-decoration: underline;
}
.boom-order-pix-card__howto i { font-size: 14px; }
/* Reskin of the REAL vendor markup (woo-gerencianet-official's
   #pix-container / #gnbtncopy) rendered inside .boom-order-pix-card by
   thankyou.php's do_action() calls — the QR image and "Copia e Cola" code
   are real, live Efí data, not reproduced here. */
.boom-order-pix-card #pix-container {
	width: 100%;
	display: flex;
	flex-direction: column;
	align-items: center;
}
.boom-order-pix-card #pix-container > div { float: none !important; }
.boom-order-pix-card #pix-container h2,
.boom-order-pix-card #pix-container p {
	display: none;
}
/* initPixCardLayout() (boom.js) physically reorders the vendor's 3 real
   children (copy-button div first, QR-image div last) and moves 2 real
   elements — the "como pagar com pix?" trigger + the divider just below —
   in between them, tagging the 2 vendor divs with these stable classes
   so they're targetable regardless of their resulting DOM position. */
.boom-pix-copy-row { width: 100%; }
.boom-pix-copy-row::after {
	content: "cole no app do seu banco, no pix — mais fácil no celular";
	display: block;
	text-align: center;
	font-size: var(--text-2xs);
	color: var(--color-text-secondary);
	margin-top: var(--space-5);
}
.boom-pix-qr-row { width: 100%; text-align: center; }
.boom-pix-divider {
	display: flex;
	align-items: center;
	gap: var(--space-5);
	width: 100%;
	margin: var(--space-7) 0;
}
.boom-pix-divider__line { flex: 1; height: 1px; background: #ece9f7; }
.boom-pix-divider__text {
	font: var(--weight-semibold) 8.5px var(--font-body);
	text-transform: uppercase;
	letter-spacing: var(--tracking-eyebrow);
	color: var(--color-text-muted);
	white-space: nowrap;
}
.boom-order-pix-card #pix-container img {
	width: 170px;
	height: 170px;
	display: block;
	margin: 0 auto;
	border: var(--border-hairline);
	border-radius: var(--radius-md);
	object-fit: contain;
}
.boom-order-pix-card #gnbtncopy {
	margin-top: var(--space-8);
	width: 100%;
	background: var(--color-bg-cta);
	color: var(--color-text-on-dark);
	border: none;
	border-radius: var(--radius-md);
	padding: var(--space-7);
	font: var(--font-button);
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	text-decoration: none;
	text-align: center;
}

/* "Como pagar com pix?" help modal — same theme-owned centered-modal/
   shared-backdrop convention as .boom-link-preview-popup (z-index 91,
   matching every other popup against the shared .boom-popup-backdrop's
   z-index 90). */
.boom-pix-howto-popup {
	display: none;
	position: fixed; z-index: 91;
	top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 90%;
	max-height: calc(100% - 2 * var(--page-margin));
	box-sizing: border-box;
	overflow-y: auto;
}
.boom-pix-howto-popup.is-open { display: block; }
.boom-pix-howto-popup__inner {
	background: var(--color-bg-surface);
	border-radius: var(--radius-xl);
	border-top: 4px solid var(--color-text-brand);
	padding: var(--space-8);
	box-shadow: var(--shadow-xl);
}
.boom-pix-howto-popup__head { display: flex; align-items: center; gap: var(--space-5); margin-bottom: var(--space-7); }
.boom-pix-howto-popup__head-icon {
	width: 30px;
	height: 30px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface-violet-50);
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}
.boom-pix-howto-popup__head-icon i { font-size: 16px; color: var(--color-text-brand); }
.boom-pix-howto-popup__head-title {
	flex: 1;
	font: var(--weight-bold) var(--text-base) var(--font-display);
	color: var(--color-text-primary);
}
.boom-pix-howto-popup__close {
	width: 30px;
	height: 30px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface-tint);
	border: none;
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	flex-shrink: 0;
}
.boom-pix-howto-popup__close i { font-size: 16px; color: var(--color-text-secondary); }
.boom-pix-howto-popup__steps {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--space-7);
}
.boom-pix-howto-popup__steps li { display: flex; align-items: flex-start; gap: var(--space-6); }
.boom-pix-howto-popup__num {
	width: 22px;
	height: 22px;
	border-radius: 50%;
	background: var(--color-text-brand);
	color: #fff;
	font-size: 10px;
	font-weight: var(--weight-bold);
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}
.boom-pix-howto-popup__steps li span:last-child {
	font-size: var(--text-xs);
	color: var(--color-text-secondary);
	line-height: var(--leading-relaxed);
}
.boom-pix-howto-popup__done { margin-top: var(--space-8); width: 100%; }

/* Popup width — mobile 90%, desktop/tablet +20% over each popup's own
   previous fixed size (2026-07-27, user request, explanation.md #207;
   mandatory site-wide, CLAUDE.md #44). Mobile (every popup's own base
   rule, edited individually above) dropped the old min(Xpx, calc(100% -
   2*var(--page-margin))) cap in favor of a flat 90% of viewport width.
   Desktop/tablet (this project's one shell breakpoint, desktop-nav.css)
   keeps each popup's own distinct target size, just each one's old value
   × 1.2, consolidated here in one place rather than scattered as N
   separate @media blocks next to each popup's own rule — easier to audit
   that every popup actually got the same treatment. .boom-cart-popup's
   own 384px override already lived elsewhere before this and is
   unaffected (320×1.2 = 384, already correct — added 2026-07-27 earlier
   the same day, explanation.md §202). .ui-dialog (home.js's confirm-link/
   help/error states) and .boom-phone-input__panel (the country-picker
   dropdown, not a centered modal) are deliberately excluded — neither is
   part of this `.boom-*-popup` family. */
@media (min-width: 480px) {
	.boom-cart-added-popup { width: min(324px, calc(100% - 2 * var(--page-margin))); }
	.boom-cart-added-popup[data-state="loading"] { width: min(360px, calc(100% - 2 * var(--page-margin))); }
	.boom-all-promos-popup { width: min(432px, calc(100% - 2 * var(--page-margin))); }
	.boom-today-promo-popup { width: min(384px, calc(100% - 2 * var(--page-margin))); }
	.boom-avaliacao-popup { width: min(384px, calc(100% - 2 * var(--page-margin))); }
	.boom-assinatura-popup { width: min(432px, calc(100% - 2 * var(--page-margin))); }
	.boom-cashboom-popup { width: min(384px, calc(100% - 2 * var(--page-margin))); }
	.boom-link-preview-popup { width: min(384px, calc(100% - 2 * var(--page-margin))); }
	.boom-bestsellers-popup,
	.boom-status-popup,
	.boom-brinde-popup,
	.boom-modo-escuro-popup,
	.boom-myaccount-expired-popup,
	.boom-myaccount-whereuse-popup { width: min(384px, calc(100% - 2 * var(--page-margin))); }
	.boom-boomplus-popup { width: min(384px, calc(100% - 2 * var(--page-margin))); }
	.boom-servico-popup { width: min(384px, calc(100% - 2 * var(--page-margin))); }
	.boom-checkout-login-popup { width: min(384px, calc(100% - 2 * var(--page-margin))); }
	.boom-pix-howto-popup { width: min(408px, calc(100% - 2 * var(--page-margin))); }
	/* "monte seu pedido" picker popups — base 320px × 1.2 (mandatory two-tier
	   width rule, CLAUDE.md #45), same 384px several other popups above land
	   on too, not a coincidence — it's just the shared ×1.2 formula. */
	.boom-order-picker__card { width: min(384px, calc(100% - 2 * var(--page-margin))); }
	.boom-service-rules-popup { width: min(384px, calc(100% - 2 * var(--page-margin))); }
}

/* Paid-state placeholder for the same do_action() calls (any other
   gateway/plugin's own woocommerce_thankyou listener still needs to fire
   for parity) — nothing visible, there's no QR/payment step left. */
.boom-order-hooks-sink { display: none; }

.boom-order-items { display: flex; flex-direction: column; }
.boom-order-item {
	display: flex;
	align-items: flex-start;
	gap: var(--space-6);
	padding: var(--space-6) 0;
	border-bottom: var(--border-hairline);
}
.boom-order-items .boom-order-item:last-child { border-bottom: none; }
.boom-order-item__body { min-width: 0; flex: 1; }
.boom-order-item__meta { margin-top: var(--space-2); }
.boom-order-item__meta .wc-item-meta {
	list-style: none;
	margin: 0;
	padding: 0;
	font: var(--text-2xs) var(--font-body);
	color: var(--color-text-muted);
	word-break: break-all;
}
.boom-order-item__meta .wc-item-meta li { margin: 0; }
.boom-order-item__purchase-note {
	font: var(--text-2xs) var(--font-body);
	color: var(--color-text-secondary);
	padding: var(--space-4) 0;
}

.boom-order-totals { display: flex; flex-direction: column; gap: var(--space-4); padding-top: var(--space-7); }
.boom-order-totals__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); }
.boom-order-totals__row:last-child {
	margin-top: var(--space-2);
	padding-top: var(--space-7);
	border-top: var(--border-hairline);
}
.boom-order-totals__row:last-child .boom-order-totals__label,
.boom-order-totals__row:last-child .boom-order-totals__value {
	font: var(--weight-bold) var(--text-md) var(--font-display);
	color: var(--color-text-primary);
}
.boom-order-totals__row:last-child .boom-order-totals__value { color: var(--color-text-brand-deep); }
.boom-order-totals__label { font: var(--text-xs) var(--font-body); color: var(--color-text-secondary); }
.boom-order-totals__value { font: var(--weight-semibold) var(--text-sm) var(--font-body); color: var(--color-text-primary); }
.boom-order-totals__row--discount .boom-order-totals__label,
.boom-order-totals__row--discount .boom-order-totals__value {
	color: var(--color-text-success);
}

.boom-order-note {
	margin-top: var(--space-6);
	padding-top: var(--space-6);
	border-top: var(--border-hairline);
	font: var(--text-2xs) var(--font-body);
	color: var(--color-text-secondary);
}

.boom-order-summary__rows { display: flex; flex-direction: column; gap: var(--space-5); }
.boom-order-summary__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); }
.boom-order-summary__label { font: var(--text-2xs) var(--font-body); color: var(--color-text-secondary); }
.boom-order-summary__value {
	font: var(--weight-semibold) var(--text-xs) var(--font-body);
	color: var(--color-text-primary);
	text-align: right;
}

.boom-order-notfound { text-align: center; color: var(--color-text-secondary); font: var(--text-sm) var(--font-body); }

/* ==========================================================================
   Single product page (single-product-boom.php)
   ========================================================================== */

/* ---------- Hero price row ---------- */
.boom-hero__price-row {
	display: flex;
	align-items: center;
	margin-top: var(--space-5);
	padding-top: var(--space-4);
	border-top: 0.5px solid rgba(255, 255, 255, 0.1);
}
.boom-hero__price {
	font-family: var(--font-body);
	font-weight: var(--weight-bold);
	font-size: var(--text-sm);
	color: var(--color-text-on-dark);
}

/* ---------- Product description (real the_content(), styled generically) ----------
   Most products' post_content already follows a #o-que/#por-que/#boom/
   #comprar/#dicas <section>+<h2> convention (see single-product-boom.php's
   header comment) -- these rules target the plain tags that convention (and
   any other product's plain content) already uses, not per-product markup. */
.boom-product-description {
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	border-radius: var(--radius-lg);
	padding: var(--card-padding);
}
.boom-product-description > *:first-child { margin-top: 0; }
.boom-product-description h2 {
	font-family: var(--font-display);
	font-weight: var(--weight-bold);
	font-size: var(--text-lg);
	color: var(--color-text-primary);
	line-height: var(--leading-tight);
	margin: var(--space-11) 0 var(--space-6);
}
.boom-product-description section {
	margin-top: var(--space-10);
	padding-top: var(--space-10);
	border-top: var(--border-hairline);
}
.boom-product-description section:first-of-type {
	margin-top: var(--space-9);
	padding-top: 0;
	border-top: none;
}
.boom-product-description p {
	font: var(--font-body-md);
	color: var(--color-text-secondary);
	line-height: var(--leading-relaxed, 1.7);
	margin: 0 0 var(--space-6);
}
.boom-product-description ul,
.boom-product-description ol {
	margin: 0 0 var(--space-6);
	padding: 0;
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: var(--space-5);
}
.boom-product-description ul li,
.boom-product-description ol li {
	font: var(--font-body-md);
	color: var(--color-text-secondary);
	line-height: var(--leading-relaxed, 1.7);
	padding-left: var(--space-10);
	position: relative;
}
.boom-product-description ul li::before {
	content: '\2713';
	position: absolute;
	left: 0;
	top: 0;
	color: var(--color-text-brand);
	font-weight: var(--weight-bold);
}
.boom-product-description ol {
	counter-reset: boom-product-desc-step;
}
.boom-product-description ol li::before {
	counter-increment: boom-product-desc-step;
	content: counter(boom-product-desc-step);
	position: absolute;
	left: 0;
	top: -1px;
	width: 18px;
	height: 18px;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	color: var(--color-text-brand-deep);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	display: flex;
	align-items: center;
	justify-content: center;
}
.boom-product-description strong { color: var(--color-text-primary); }
.boom-product-description a {
	color: var(--color-link);
	text-decoration: underline;
}
.boom-product-description .summary {
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-md);
	padding: var(--space-8);
	margin: 0 0 var(--space-9);
}
.boom-product-description .summary h2 {
	font: var(--font-eyebrow);
	text-transform: uppercase;
	letter-spacing: var(--tracking-eyebrow);
	color: var(--color-text-brand-deep);
	margin: 0 0 var(--space-5);
}
.boom-product-description .summary ul {
	gap: var(--space-4);
}
.boom-product-description .summary ul li {
	padding-left: 0;
	font: var(--font-label);
}
.boom-product-description .summary ul li::before { content: none; }
.boom-product-description .summary a { text-decoration: none; }
.boom-product-description figure {
	margin: var(--space-9) 0 0;
	text-align: center;
}
.boom-product-description figure img {
	width: auto;
	max-width: 120px;
	height: auto;
	display: inline-block;
}

/* ---------- Related products grid ---------- */
.boom-related-products__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--space-6);
}
.boom-related-products__card {
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	border-radius: var(--radius-lg);
	padding: var(--space-8);
	display: flex;
	flex-direction: column;
	text-decoration: none;
}
.boom-related-products__icon {
	width: 30px;
	height: 30px;
	border-radius: var(--radius-md);
	background: var(--color-bg-surface-tint);
	display: flex;
	align-items: center;
	justify-content: center;
}
.boom-related-products__icon i { font-size: 15.6px; color: var(--color-text-brand); }
.boom-related-products__name {
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	color: var(--color-text-primary);
	line-height: 1.35;
	margin: var(--space-6) 0 0;
}
.boom-related-products__price {
	font-size: var(--text-2xs);
	color: var(--color-text-secondary);
	margin: var(--space-3) 0 0;
}
.boom-related-products__cta {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	color: var(--color-text-brand);
	margin-top: var(--space-6);
}
.boom-related-products__cta i { font-size: 10px; }

.boom-related-products__footer {
	margin-top: var(--space-8);
	text-align: center;
}
/* Same solid-pill CTA look as the desktop nav's own "comprar" button
   (.boom-nav-cta's violet-gradient/rounded treatment) and
   .boom-bestseller-card__cta's --color-bg-cta pattern -- text only here,
   no icon, per the mockup. */
.boom-related-products__see-all {
	display: inline-block;
	background: var(--color-bg-cta);
	color: #fff;
	border-radius: var(--radius-pill);
	padding: var(--space-6) var(--space-10);
	font-size: 11.7px;
	font-weight: var(--weight-bold);
	text-decoration: none;
}

/* ==========================================================================
   My Account -- real design (2026-07-26). See explanation.md's "Minha conta
   (My Account) -- TODO de progresso" for status/scope. .boom-myaccount-*
   is new; the popup shell itself reuses the shared "cards grid popups"
   group above (.boom-myaccount-expired-popup joined that selector, not a
   new shell here) and .boom-faq/.boom-cashboom-popup are reused as-is.
   ========================================================================== */

/* ---- Header (avatar, name, tier badge, actions) ---- */
.boom-myaccount-header__subtitle {
	font-size: 10.5px;
	color: var(--violet-300);
	margin: var(--space-2) 0 0;
}

.boom-myaccount-header {
	background: var(--color-bg-cta);
	border: none;
	color: #fff;
}
.boom-myaccount-header__row {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--space-7);
}
.boom-myaccount-header__avatar {
	flex-shrink: 0;
	width: 48px; height: 48px;
	border-radius: var(--radius-pill);
	background: rgba(255, 255, 255, 0.18);
	color: #fff;
	font: var(--weight-bold) var(--text-lg) var(--font-display);
	display: flex; align-items: center; justify-content: center;
}
.boom-myaccount-header__id { min-width: 0; flex: 1; }
.boom-myaccount-header__hello {
	font: var(--weight-bold) var(--text-md) var(--font-display);
	color: #fff;
	margin: 0;
}
.boom-myaccount-header__tier {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	color: var(--color-text-brand-deep);
	background: var(--color-bg-surface);
	border-radius: var(--radius-pill);
	padding: 2px var(--space-5);
	margin-top: var(--space-3);
}
.boom-myaccount-header__logout {
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	background: rgba(255, 255, 255, 0.16);
	border-radius: var(--radius-pill);
	padding: var(--space-3) var(--space-6);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	text-decoration: none;
}
.boom-myaccount-header__contact {
	font-size: var(--text-xs);
	color: var(--violet-300);
	margin: var(--space-6) 0 0;
	overflow-wrap: anywhere;
}
.boom-myaccount-header__edit {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	font-size: var(--text-xs);
	font-weight: var(--weight-semibold);
	text-decoration: underline;
	margin-top: var(--space-5);
}

/* ---- "o que você ganha fazendo pedidos" ---- */
.boom-myaccount-benefits__grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--space-7);
}
.boom-myaccount-benefit {
	position: relative;
	background: var(--color-bg-surface-tint);
	border-radius: var(--radius-md);
	padding: var(--space-7);
}
.boom-myaccount-benefit__icon {
	display: inline-flex; align-items: center; justify-content: center;
	width: 28px; height: 28px;
	border-radius: var(--radius-sm);
	background: var(--color-bg-surface);
	box-shadow: var(--shadow-xs);
	margin-bottom: var(--space-5);
}
.boom-myaccount-benefit__icon i { font-size: 15px; color: var(--color-text-brand-deep); }
.boom-myaccount-benefit__title {
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	color: var(--color-text-primary);
	margin: 0 0 var(--space-3);
}
.boom-myaccount-benefit__desc {
	font-size: 10.5px;
	line-height: var(--leading-normal);
	color: var(--color-text-secondary);
	margin: 0;
}

/* ---- Welcome banner (zero orders yet) ---- */
.boom-myaccount-welcome__title {
	font: var(--font-section-title);
	color: var(--color-text-primary);
	margin: 0 0 var(--space-4);
}
.boom-myaccount-welcome__desc {
	font-size: var(--text-xs);
	color: var(--color-text-secondary);
	margin: 0 0 var(--space-8);
}

/* ---- Stats row ---- */
.boom-myaccount-stats {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--space-7);
}
.boom-myaccount-stat {
	text-align: center;
}
.boom-myaccount-stat__icon {
	display: block;
	margin-bottom: var(--space-4);
}
.boom-myaccount-stat__icon i { font-size: 15px; color: var(--color-text-brand); }
.boom-myaccount-stat__value {
	display: block;
	font: var(--weight-bold) var(--text-xl) var(--font-display);
	color: var(--color-text-brand-deep);
}
.boom-myaccount-stat__value--accent { color: var(--color-text-brand-deep); }
.boom-myaccount-stat__label {
	display: block;
	font-size: var(--text-2xs);
	color: var(--color-text-secondary);
	margin-top: var(--space-3);
}
.boom-myaccount-stat__sub {
	display: block;
	font-size: var(--text-2xs);
	color: var(--color-text-muted);
	margin-top: var(--space-2);
}

/* ---- CASHBOOM ---- */
.boom-myaccount-cashboom__sub {
	font: var(--weight-medium) var(--text-2xs) var(--font-body);
	text-transform: none;
	color: var(--color-text-secondary);
}
.boom-myaccount-cashboom__grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--space-7);
	margin-bottom: var(--space-7);
}
.boom-myaccount-cashboom-card__title {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	color: var(--color-text-primary);
	margin: 0 0 var(--space-5);
}
.boom-myaccount-cashboom-card__title i { font-size: 12px; color: var(--color-text-brand-deep); }
.boom-myaccount-cashboom-card__rules-btn {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	background: var(--color-bg-surface);
	border: var(--border-hairline);
	border-radius: var(--radius-pill);
	padding: var(--space-3) var(--space-6);
	font-size: 10px;
	font-weight: var(--weight-bold);
	color: var(--color-text-brand);
	cursor: pointer;
	margin-top: var(--space-6);
}
.boom-myaccount-cashboom-card__rules-btn i { font-size: 10px; }
.boom-myaccount-cashboom-card__progress-label {
	font-size: var(--text-2xs);
	color: var(--color-text-secondary);
	margin: 0 0 var(--space-3);
}
.boom-myaccount-cashboom-card__bar {
	height: 6px;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
	overflow: hidden;
	margin-bottom: var(--space-5);
}
.boom-myaccount-cashboom-card__bar span {
	display: block;
	height: 100%;
	background: var(--color-bg-cta);
	border-radius: var(--radius-pill);
}
.boom-myaccount-cashboom-card__hint,
.boom-myaccount-cashboom-card__balance {
	font-size: 10.5px;
	line-height: var(--leading-normal);
	color: var(--color-text-secondary);
	margin: 0;
}
/* ---- Coupon lists (CASHBOOM + "outros cupons de desconto") ---- */
/* ---- Outer cashboom/coupon cards -- subtle purple-tinted shadow, one
   continuous card per section, matching the live mockup (2026-07-26). ---- */
.boom-myaccount-cashboom,
.boom-myaccount-coupons {
	box-shadow: 0 1px 3px rgba(109, 40, 217, 0.06);
}
.boom-myaccount-cashboom__rules-trigger { text-decoration: underline; }

/* ---- Empty-state icon box (cashboom coupons + outros coupons) ---- */
.boom-myaccount-coupons__empty-box {
	display: flex;
	align-items: center;
	gap: var(--space-5);
	border-radius: var(--radius-md);
	padding: var(--space-6);
}
.boom-myaccount-coupons__empty-box--dashed {
	border: 0.5px dashed var(--color-border-subtle);
}
.boom-myaccount-coupons__empty-box--tint {
	background: var(--color-bg-surface-tint);
}
.boom-myaccount-coupons__empty-icon {
	flex-shrink: 0;
	width: 32px;
	height: 32px;
	border-radius: var(--radius-md);
	display: flex;
	align-items: center;
	justify-content: center;
}
.boom-myaccount-coupons__empty-box--dashed .boom-myaccount-coupons__empty-icon {
	background: var(--color-bg-page);
}
.boom-myaccount-coupons__empty-box--tint .boom-myaccount-coupons__empty-icon {
	background: var(--color-bg-surface);
}
.boom-myaccount-coupons__empty-icon i {
	font-size: 15px;
	color: var(--color-text-muted);
}
.boom-myaccount-coupons__empty-content { flex: 1; min-width: 0; }
.boom-myaccount-coupons__empty {
	font-size: var(--text-xs);
	color: var(--color-text-secondary);
	margin: 0;
}
.boom-myaccount-coupons__empty-hint {
	font-size: 10.5px;
	color: var(--color-text-muted);
	margin: var(--space-3) 0 0;
}
.boom-myaccount-coupons__list {
	display: flex;
	flex-direction: column;
	gap: var(--space-5);
}
.boom-myaccount-coupons__expired-btn {
	display: block;
	width: 100%;
	margin-top: var(--space-6);
	background: var(--color-bg-surface-tint);
	border: none;
	border-radius: var(--radius-md);
	padding: var(--space-6);
	font-size: var(--text-2xs);
	font-weight: var(--weight-semibold);
	color: var(--color-text-secondary);
	cursor: pointer;
}

.boom-myaccount-coupon {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-5);
	border: var(--border-hairline);
	border-radius: var(--radius-md);
	padding: var(--space-6);
}
.boom-myaccount-coupon--inactive { opacity: 0.55; }
.boom-myaccount-coupon__value {
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	color: var(--color-text-primary);
	margin: 0;
}
.boom-myaccount-coupon__meta {
	font-size: 10.5px;
	color: var(--color-text-secondary);
	margin: var(--space-2) 0 0;
}
.boom-myaccount-coupon__origin {
	font-size: 10px;
	color: var(--color-text-brand);
	margin: var(--space-2) 0 0;
}
.boom-myaccount-coupon__copy {
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	gap: var(--space-3);
	background: var(--color-bg-surface-violet-50);
	color: var(--color-text-brand);
	border: none;
	border-radius: var(--radius-pill);
	padding: var(--space-4) var(--space-7);
	font-size: 10.5px;
	font-weight: var(--weight-bold);
	cursor: pointer;
}
.boom-myaccount-coupon__copy.is-copied { color: var(--color-text-success); }
.boom-myaccount-coupon__status {
	flex-shrink: 0;
	font-size: 10px;
	font-weight: var(--weight-bold);
	text-transform: uppercase;
	color: var(--color-text-muted);
}

/* ---- "detectamos queda" alert (amber, real garantia/reposição
   backend already exists -- just gated pending UI validation) / "indique
   um amigo" (purple-filled, matches the account header card) ---- */
.boom-myaccount-alert {
	background: var(--color-bg-alert);
	border-color: var(--color-border-alert);
}
.boom-myaccount-referral {
	background: var(--color-bg-cta);
	border: none;
}
.boom-myaccount-alert,
.boom-myaccount-referral {
	display: flex;
	align-items: flex-start;
	gap: var(--space-6);
	flex-wrap: wrap;
}
.boom-myaccount-alert__icon,
.boom-myaccount-referral__icon {
	flex-shrink: 0;
	width: 32px; height: 32px;
	background: var(--color-bg-surface);
	display: inline-flex; align-items: center; justify-content: center;
}
.boom-myaccount-alert__icon { border-radius: 9px; }
.boom-myaccount-referral__icon { border-radius: var(--radius-pill); background: rgba(255, 255, 255, 0.18); }
.boom-myaccount-alert__icon i { font-size: 16px; color: var(--color-icon-alert); }
.boom-myaccount-referral__icon i { font-size: 16px; color: #fff; }
.boom-myaccount-alert__text,
.boom-myaccount-referral__text { flex: 1; min-width: 160px; }
.boom-myaccount-alert__title {
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	color: var(--color-text-alert);
	margin: 0;
}
.boom-myaccount-referral__title {
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	color: #fff;
	margin: 0;
}
.boom-myaccount-alert__desc {
	font-size: 10.5px;
	color: var(--color-text-alert);
	margin: var(--space-2) 0 0;
}
.boom-myaccount-referral__desc {
	font-size: 10.5px;
	color: var(--violet-300);
	margin: var(--space-2) 0 0;
}
.boom-myaccount-alert__cta {
	flex-basis: 100%;
	display: block;
	text-align: center;
	background: var(--color-bg-alert-cta);
	color: #fff;
	border-radius: 8px;
	padding: var(--space-5) var(--space-9);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	text-decoration: none;
	margin-top: var(--space-5);
}

/* ---- "seus pedidos" entry (default WooCommerce behavior, see TODO) ---- */
.boom-myaccount-orders-cta__desc {
	font-size: var(--text-xs);
	color: var(--color-text-secondary);
	margin: 0 0 var(--space-7);
}

/* ---- Dev-preview marker -- content gated by boom_is_dev_preview_user(),
   see explanation.md's My Account TODO section for the current list and
   why each item is gated. Purely a visual QA aid for developers; renders
   inline only because these blocks already only reach the HTML for
   allow-listed accounts (an if/endif, not CSS display:none). ---- */
.boom-dev-preview { position: relative; }
.boom-dev-preview__tag {
	display: inline-block;
	position: absolute;
	top: calc(-1 * var(--space-5));
	right: var(--space-6);
	background: var(--violet-700);
	color: #fff;
	font-size: 9px;
	font-weight: var(--weight-bold);
	text-transform: uppercase;
	letter-spacing: var(--tracking-eyebrow);
	border-radius: var(--radius-pill);
	padding: 2px var(--space-5);
}

/* ---- "cupons expirados" popups (shell/close/is-open joined the shared
   "cards grid popups" group above -- only this popup's own content
   classes are declared here) ---- */
.boom-myaccount-expired-popup__title {
	font: var(--font-section-title);
	color: var(--color-text-primary);
	margin: 0 0 var(--space-4);
	padding-right: var(--space-9);
}
.boom-myaccount-expired-popup__intro {
	font-size: 10.5px;
	line-height: var(--leading-normal);
	color: var(--color-text-secondary);
	margin: 0 0 var(--space-7);
}
.boom-myaccount-expired-popup__list {
	display: flex;
	flex-direction: column;
	gap: var(--space-5);
	margin-bottom: var(--space-7);
}
.boom-myaccount-expired-popup__dismiss {
	display: block;
	width: 100%;
	background: var(--color-bg-surface-tint);
	color: var(--color-text-secondary);
	border: none;
	border-radius: var(--radius-pill);
	padding: var(--space-5) var(--space-9);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	cursor: pointer;
	flex-shrink: 0;
}

@media (max-width: 480px) {
	.boom-myaccount-benefits__grid,
	.boom-myaccount-cashboom__grid { grid-template-columns: 1fr; }
}

/* ---- CASHBOOM/cupons refinement (2026-07-26, follow-up pass against the
   live mockup's Tweaks-driven coupon logic, not just its static text) ---- */

.boom-myaccount-coupons__hint-link {
	display: inline-block;
	background: none;
	border: none;
	padding: 0;
	margin-top: var(--space-3);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	color: var(--color-text-brand);
	text-decoration: underline;
	cursor: pointer;
}

.boom-myaccount-coupon__actions {
	flex-shrink: 0;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--space-5);
	align-self: stretch;
}
.boom-myaccount-coupon__whereuse {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	background: none;
	border: none;
	padding: 0;
	font-size: 10px;
	font-weight: var(--weight-bold);
	color: var(--color-text-secondary);
	text-decoration: underline;
	cursor: pointer;
}
.boom-myaccount-coupon__whereuse i { font-size: 10px; }

/* Active cashboom coupons only -- celebratory purple-gradient treatment,
   matching the live mockup exactly (expired ones stay on the plain/muted
   .boom-myaccount-coupon shape, no gradient). */
.boom-myaccount-coupon--cashboom-active {
	background: var(--color-bg-cta);
	border: none;
	box-shadow: var(--shadow-md);
}
.boom-myaccount-coupon--cashboom-active .boom-myaccount-coupon__value,
.boom-myaccount-coupon--cashboom-active .boom-myaccount-coupon__meta,
.boom-myaccount-coupon--cashboom-active .boom-myaccount-coupon__origin {
	color: #fff;
}
.boom-myaccount-coupon--cashboom-active .boom-myaccount-coupon__meta,
.boom-myaccount-coupon--cashboom-active .boom-myaccount-coupon__origin {
	color: var(--violet-300);
}
.boom-myaccount-coupon--cashboom-active .boom-myaccount-coupon__copy {
	background: var(--color-bg-surface);
	color: var(--color-text-brand);
}
.boom-myaccount-coupon--cashboom-active .boom-myaccount-coupon__whereuse {
	color: var(--violet-300);
}

/* ---- "onde usar" popup (shell/close joined the shared "cards grid
   popups" group above -- only this popup's own content here) ---- */
.boom-myaccount-whereuse-popup__title {
	font: var(--font-section-title);
	color: var(--color-text-primary);
	margin: 0 0 var(--space-4);
	padding-right: var(--space-9);
}
.boom-myaccount-whereuse-popup__text {
	font-size: 10.5px;
	line-height: var(--leading-normal);
	color: var(--color-text-secondary);
	margin: 0 0 var(--space-7);
}
.boom-myaccount-whereuse-popup__dismiss {
	display: block;
	width: 100%;
	background: var(--color-bg-cta);
	color: #fff;
	border: none;
	border-radius: var(--radius-pill);
	padding: var(--space-5) var(--space-9);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	cursor: pointer;
}

/* ---- Coupon card icon tile (2026-07-27 visual pass against the real
   rendered mockup, not just its text) ---- */
.boom-myaccount-coupon {
	align-items: flex-start;
}
.boom-myaccount-coupon__icon {
	flex-shrink: 0;
	width: 32px; height: 32px;
	border-radius: var(--radius-md);
	background: var(--color-bg-surface-tint);
	display: inline-flex; align-items: center; justify-content: center;
}
.boom-myaccount-coupon__icon i { font-size: 15px; color: var(--color-text-brand-deep); }
.boom-myaccount-coupon--cashboom-active .boom-myaccount-coupon__icon {
	background: rgba(255, 255, 255, 0.18);
}
.boom-myaccount-coupon--cashboom-active .boom-myaccount-coupon__icon i { color: #fff; }
.boom-myaccount-coupon--inactive .boom-myaccount-coupon__icon {
	background: var(--color-bg-page);
}
.boom-myaccount-coupon--inactive .boom-myaccount-coupon__icon i { color: var(--color-text-muted); }
.boom-myaccount-coupon__main { flex: 1; min-width: 0; }

/* ---- "ganhe brinde fazendo pedidos" (dev-preview only) -- weekly-streak
   progress bar + step row, matches the mockup's real render (not just its
   static text). ---- */
.boom-myaccount-brinde__head {
	display: flex;
	align-items: flex-start;
	gap: var(--space-6);
	margin-bottom: var(--space-7);
}
.boom-myaccount-brinde__icon {
	flex-shrink: 0;
	width: 32px; height: 32px;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-violet-50);
	display: inline-flex; align-items: center; justify-content: center;
}
.boom-myaccount-brinde__icon i { font-size: 16px; color: var(--color-text-brand-deep); }
.boom-myaccount-brinde__title {
	font-size: var(--text-xs);
	font-weight: var(--weight-bold);
	color: var(--color-text-primary);
	margin: 0;
}
.boom-myaccount-brinde__sub {
	font-size: 10.5px;
	color: var(--color-text-secondary);
	margin: var(--space-2) 0 0;
}
.boom-myaccount-brinde__bar {
	display: flex;
	gap: var(--space-3);
	margin-bottom: var(--space-5);
}
.boom-myaccount-brinde__bar-seg {
	flex: 1;
	height: 6px;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-tint);
}
.boom-myaccount-brinde__bar-seg.is-done { background: var(--color-text-brand); }
.boom-myaccount-brinde__steps {
	display: flex;
	justify-content: space-between;
	margin-bottom: var(--space-6);
}
.boom-myaccount-brinde__step {
	width: 24px; height: 24px;
	border-radius: var(--radius-pill);
	background: var(--color-bg-surface-violet-50);
	color: var(--color-text-muted);
	display: inline-flex; align-items: center; justify-content: center;
}
.boom-myaccount-brinde__step.is-done { background: var(--color-text-brand); color: #fff; }
.boom-myaccount-brinde__step i { font-size: 11px; }
.boom-myaccount-brinde__banner {
	text-align: center;
	background: var(--color-bg-surface-violet-50);
	color: var(--color-text-brand-deep);
	border-radius: var(--radius-md);
	padding: var(--space-5);
	font-size: var(--text-2xs);
	font-weight: var(--weight-bold);
	margin: 0;
}
