/**
 * MerchLab Studio — full site redesign.
 * WoodMart remains the token and commerce foundation.
 */

.ml-site,
.ml-site * {
	box-sizing: border-box;
}

.ml-site {
	width: 100%;
	min-width: 0;
	color: var(--wd-text-color);
	background: var(--wd-main-bgcolor, #fdf6e3);
}

:root {
	/* Visual Style Update 2026-09-15: cream base (was #f2f2ef). */
	--wd-main-bgcolor: #faeec6;
}

body,
.wd-page-wrapper,
.main-page-wrapper {
	background-color: var(--wd-main-bgcolor) !important;
}

.wd-content-layout > .ml-site {
	grid-column: 1 / -1;
}

.ml-shell {
	width: min(calc(100% - 48px), var(--wd-container-w));
	margin-inline: auto;
}

.ml-section {
	padding-block: clamp(72px, 9vw, 144px);
}

.ml-section--compact {
	padding-block: clamp(48px, 6vw, 88px);
}

.ml-kicker {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	margin: 0 0 24px;
	color: var(--wd-link-color-hover);
	font: 600 11px/1.2 var(--wd-text-font);
	letter-spacing: .18em;
	text-transform: uppercase;
}

.ml-kicker::before {
	width: 28px;
	height: 2px;
	background: var(--wd-alternative-color);
	content: "";
}

.ml-display {
	max-width: 14ch;
	margin: 0;
	color: var(--wd-title-color);
	font: 600 clamp(48px, 7.2vw, 116px)/.9 var(--wd-title-font);
	letter-spacing: -.065em;
	text-wrap: balance;
}

.ml-title {
	max-width: 18ch;
	margin: 0;
	color: var(--wd-title-color);
	font: 600 clamp(38px, 5vw, 76px)/.96 var(--wd-title-font);
	letter-spacing: -.055em;
	text-wrap: balance;
}

.ml-lead {
	max-width: 60ch;
	margin: 0;
	color: var(--wd-text-color);
	font: 400 clamp(17px, 1.5vw, 21px)/1.55 var(--wd-text-font);
}

/* Ph14 DEV-16 (14-09): geometry/typography aliased onto the canonical --ml-btn-* contract
   (14-03) so home-hero CTAs converge with product/cart/checkout/request -- color/hover
   semantics (dark-fill vs light-fill) are untouched. Explicit height (not just min-height)
   is required here: the --yellow variant's .ml-arrow icon (18 px font-size/line-height) makes
   its natural content-driven row height taller (52 px) than the --light variant's plain-text
   sibling (48 px) -- min-height alone can't shrink a box past its natural content size, only
   grow it, so both variants need the box pinned to the shared token explicitly. */
.ml-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 14px; /* one-off: icon-text gap, between --dof-sp-3(12) and --dof-sp-4(16) -- no exact rung, kept at its original measured value to avoid an unreviewed visual shift */
	height: var(--ml-btn-h, 48px);
	min-height: var(--ml-btn-h, 48px);
	padding: var(--ml-btn-pad, 16px 24px);
	border: 1px solid var(--wd-title-color);
	border-radius: var(--ml-btn-radius, 2px);
	background: var(--wd-title-color);
	color: var(--dof-on-dark);
	font-weight: var(--ml-btn-fw, 600);
	font-size: var(--ml-btn-fs, 11px);
	line-height: 1.2;
	font-family: var(--wd-text-font);
	letter-spacing: var(--ml-btn-ls, .14em);
	text-align: center;
	text-transform: uppercase;
	transition: background-color 180ms ease, border-color 180ms ease, color 180ms ease, transform 180ms ease;
}

.ml-button:hover {
	border-color: var(--wd-alternative-color);
	background: var(--wd-alternative-color);
	color: var(--wd-title-color);
	transform: translateY(-2px); /* one-off: decorative hover-lift micro-interaction, not a spacing/size ladder candidate */
}

.ml-button--light {
	border-color: rgba(255,255,255,.42);
	background: transparent;
	color: var(--dof-on-dark);
}

.ml-button--light:hover {
	border-color: var(--dof-bg-2);
	background: var(--dof-bg-2);
	color: var(--wd-title-color);
}

.ml-button--yellow {
	border-color: var(--wd-alternative-color);
	background: var(--wd-alternative-color);
	color: var(--wd-title-color);
}

.ml-button--yellow:hover {
	border-color: var(--dof-bg-2);
	background: var(--dof-bg-2);
	color: var(--wd-title-color);
}

.ml-arrow {
	font-size: var(--dof-icon-md, 18px);
	line-height: 1;
}

/* Ph14 DEV-16 (14-09): scoped down to the button's own font-size so the arrow glyph's line box
   no longer inflates .ml-button's natural content height past the shared --ml-btn-h token (was
   52 px vs the --light variant's 48 px, purely because this ONE variant's arrow icon is present) --
   .ml-arrow's larger --dof-icon-md size is kept everywhere else it's used (unscoped selector above). */
.ml-button .ml-arrow {
	font-size: inherit;
	line-height: inherit;
}

/* Header: one studio bar, not two unrelated navigation rows. */
body:not(.lumise-editor-page) .whb-top-bar {
	display: none !important;
}

body:not(.lumise-editor-page) .whb-header,
body:not(.lumise-editor-page) .whb-main-header {
	min-height: 0 !important;
}

body:not(.lumise-editor-page) .whb-general-header {
	height: 78px !important;
	border-bottom: 1px solid rgba(255,255,255,.14);
}

body:not(.lumise-editor-page) .whb-general-header .woodmart-nav-link {
	min-height: 44px;
	font-size: 11px !important;
	letter-spacing: .08em;
}

@media (min-width: 1025px) {
	body:not(.lumise-editor-page) .whb-general-header .wd-nav-main {
		flex-wrap: nowrap !important;
		gap: 0 11px !important;
	}

	body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li > a {
		padding-inline: 0 !important;
		font-size: 10px !important;
		letter-spacing: .045em !important;
	}
}

body:not(.lumise-editor-page) .whb-general-header .whb-column {
	gap: clamp(12px, 1.6vw, 28px);
}

/* FB-09: 1025-1350px is an unhandled gap between Woodmart's own hardcoded
   mobile/desktop header cutover (max-width:1024px / min-width:1025px, confirmed
   in Woodmart core CSS -- no adjustable breakpoint option or per-element
   responsive-visibility lever exists, see 12-01/12-06 SUMMARY). In this band
   the right header column (phone plate + login + cart) does not fit its own
   flex-basis and, because it is right-aligned (justify-content:flex-end),
   overflows LEFTWARD on top of the main nav's last item ("КОНТАКТИ"). Band-
   scoped spacing/padding tightening only -- no structural change, no redesign
   (DEV-01/Ph14 owns any real header rework). Verified overlap-free across the
   full 1025-1350px sweep (qa-phase12.js --only=fb09 + manual bisection).
   14-08 Task 3 VERDICT (retest after the DEV-01 IA restructure landed 6
   top-level items): fb09 + dev01's own rect.top/overlap asserts both stay
   GREEN with this block neutralized (tested live), BUT a finer text-node
   line-count measurement (Range.getClientRects, not just rect.top parity --
   see qa-phase14.js dev01, which only asserts item-container top alignment,
   not per-item internal wrap) found a genuine regression the coarser check
   missed: the 2-word item "Про нас" wraps to 2 lines at exactly 1152px (one
   of the 7 mandated sweep widths) without this block's font-size/letter-
   spacing squeeze. All other 6 sweep widths (1024/1200/1280/1350/1366/1440)
   stayed single-line. Per the plan's ruling ("иначe не трогать" on any
   regression) this block STAYS -- not superseded by DEV-01, kept exactly as
   written pre-14-08. */
@media (min-width: 1025px) and (max-width: 1350px) {
	body:not(.lumise-editor-page) .whb-general-header .whb-column {
		gap: 1px !important;
	}

	body:not(.lumise-editor-page) .whb-general-header .whb-space-element {
		display: none !important;
	}

	body:not(.lumise-editor-page) .whb-general-header #menu-telefony .woodmart-nav-link {
		padding: 5px 2px !important;
		font-size: 10px !important;
	}

	body:not(.lumise-editor-page) .whb-general-header .wd-nav-main {
		gap: 0 2px !important;
	}

	body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li > a {
		font-size: 9px !important;
		letter-spacing: 0 !important;
	}

	body:not(.lumise-editor-page) .whb-general-header .wd-header-my-account .wd-tools-text {
		font-size: 10px !important;
	}
}

body:not(.lumise-editor-page) .whb-general-header .wd-header-cart .wd-tools-icon,
body:not(.lumise-editor-page) .whb-general-header .wd-header-cart .wd-tools-icon::before {
	color: var(--dof-on-dark) !important;
	opacity: 1 !important;
}

/* Ph14 DEV-07 — sticky-clone header cart-amount contrast (P0). Root cause (live-verified,
   qa-phase14.js --only=dev07): dof.css's `.whb-header .wd-header-cart .wd-cart-subtotal
   { color:var(--dof-on-dark) }` rule only matches elements carrying the `.whb-header` class. Woodmart
   renders the sticky/scrolled state as a SEPARATE cloned header element (`.whb-clone`, not
   `.whb-header` — RESEARCH Pitfall 1: sticky-header-clone CSS drift), so the clone's cart
   amount silently falls back to Woodmart's default rgb(51,51,51) on its own near-black row
   -> measured 1.57:1. Selectors below are written generically to cover BOTH the page-top
   AND sticky-clone states so future clone drift can't reopen this. `.wd-cart-number` (the
   yellow qty badge) is deliberately excluded — it is already correct and out of scope. */
body:not(.lumise-editor-page) :is(.whb-header, .whb-clone) .wd-header-cart .wd-cart-subtotal,
body:not(.lumise-editor-page) :is(.whb-header, .whb-clone) .wd-header-cart .wd-tools-text,
body:not(.lumise-editor-page) :is(.whb-header, .whb-clone) .wd-header-cart .wd-tools-text-cart {
	color: var(--dof-on-dark) !important;
}

/* Belt-and-braces: pin the clone row's background explicitly to the same solid near-black
   the main header row already carries (live-verified via Woodmart's whb-color-dark class —
   this is currently a no-op backstop, not a fix for a currently-transparent bg, but protects
   against a future Header Builder config change silently dropping it). */
body:not(.lumise-editor-page) .whb-clone .whb-general-header {
	background-color: var(--dof-surface-dark) !important;
}

.merchlab-sticky-wordmark {
	display: inline-flex;
	align-items: baseline;
	color: var(--dof-on-dark);
	font-family: var(--wd-title-font);
	font-size: clamp(24px, 2vw, 30px);
	font-weight: 600;
	letter-spacing: -.04em;
	line-height: 1;
	text-decoration: none;
	white-space: nowrap;
}

.merchlab-sticky-wordmark:hover {
	color: var(--dof-on-dark);
}

.merchlab-sticky-wordmark__lab {
	color: var(--wd-alternative-color);
}

/* Home hero */
.ml-home-hero {
	position: relative;
	min-height: calc(100svh - 78px);
	overflow: hidden;
	background: var(--wd-title-color);
	color: var(--dof-on-dark);
}

.ml-home-hero__grid {
	display: grid;
	grid-template-columns: minmax(0, .88fr) minmax(480px, 1.12fr);
	min-height: calc(100svh - 78px);
}

.ml-home-hero__copy {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	padding: clamp(56px, 7vw, 104px) clamp(28px, 6vw, 88px);
	background:
		linear-gradient(150deg, color-mix(in srgb, var(--wd-title-color) 92%, transparent), var(--wd-title-color));
}

.ml-home-hero__copy .ml-kicker {
	color: var(--wd-alternative-color);
}

.ml-home-hero__copy .ml-display {
	max-width: 9ch;
	color: var(--dof-on-dark);
}

.ml-home-hero__copy .ml-display em {
	color: var(--wd-alternative-color);
	font-style: normal;
}

.ml-home-hero__copy .ml-lead {
	max-width: 48ch;
	margin-top: 30px;
	color: rgba(255,255,255,.72);
}

.ml-home-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin-top: 36px;
}

.ml-home-hero__media {
	position: relative;
	min-height: 620px;
}

.ml-home-hero__media::after {
	position: absolute;
	inset: 0;
	background: linear-gradient(90deg, color-mix(in srgb, var(--dof-ink) 35%, transparent), transparent 35%);
	content: "";
	pointer-events: none;
}

.ml-home-hero__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center center;
}

.ml-home-hero__note {
	position: absolute;
	right: 28px;
	bottom: 28px;
	z-index: 2;
	width: min(300px, calc(100% - 56px));
	padding: 22px;
	border-left: 4px solid var(--wd-alternative-color);
	background: color-mix(in srgb, var(--dof-ink) 88%, transparent);
	color: var(--dof-on-dark);
	backdrop-filter: blur(10px);
}

.ml-home-hero__note strong,
.ml-home-hero__note span {
	display: block;
}

.ml-home-hero__note strong {
	margin-bottom: 6px;
	font-size: 15px;
}

.ml-home-hero__note span {
	color: rgba(255,255,255,.68);
	font-size: 13px;
	line-height: 1.5;
}

/* Ph14 DEV-02 — hero CTA into the first viewport at 1280x720 (P1). Root cause
   (live-verified, qa-phase14.js --only=dev02, measured via headless probe this
   session): .ml-home-hero__grid/.ml-home-hero__copy both carry
   min-height:calc(100svh - 78 px), and at 1280 width the base .ml-display clamp
   resolves to 7.2vw=92.16 px -- combined with the hero-specific max-width:9ch and
   a narrow copy column, the H1 wraps to 5 lines (414.7 px tall), pushing total
   copy content past the svh-bound row height and forcing BOTH hero CTAs below
   y=720 (measured before-fix: 826.7/890.7). Scoped to 1025-1439 px only (the
   assert viewport) so the large-display look the plan calls out is UNCHANGED at
   >=1440 (still the base 7.2vw clamp there) and mobile (<=767, its own svh +
   safe-area block below) is untouched. Measured after-fix at 1280x720: both CTA
   bottoms 597.9/661.9 (>=58 px clear of the 720 fold line). */
@media (min-width: 1025px) and (max-width: 1439px) {
	.ml-home-hero__copy {
		padding: 36px clamp(28px, 6vw, 64px) 64px; /* one-off: live-measured 1025-1439px viewport fix, see comment above -- not a ladder rung, scoped narrowly on purpose */
	}

	.ml-home-hero__copy .ml-display {
		font-size: 72px; /* one-off: measured clamp override for this viewport band, see comment above */
		line-height: .95;
	}

	.ml-home-hero__copy .ml-lead {
		margin-top: 14px; /* one-off: measured viewport-band adjustment, see comment above */
	}

	.ml-home-hero__actions {
		margin-top: 18px; /* one-off: measured viewport-band adjustment, see comment above */
	}
}

/* -- DEV-02 marker scope ends above. The .ml-proofbar* rules below predate this phase
   (2026-07-23, git blame-verified) and are unaudited legacy, per this closeout's
   "phase-added blocks only" scope guard -- not re-swept here. -- */
.ml-proofbar {
	border-bottom: 1px solid var(--wd-form-brd-color);
	background: var(--dof-bg-2);
}

.ml-proofbar__grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

.ml-proofbar__item {
	padding: 28px clamp(18px, 3vw, 42px);
	border-right: 1px solid var(--wd-form-brd-color);
}

.ml-proofbar__item:last-child {
	border-right: 0;
}

.ml-proofbar__value {
	display: block;
	margin-bottom: 5px;
	color: var(--wd-title-color);
	font: 600 clamp(24px, 2.8vw, 42px)/1 var(--wd-title-font);
	letter-spacing: -.04em;
}

.ml-proofbar__label {
	color: var(--wd-text-color);
	font-size: 12px;
	text-transform: uppercase;
	letter-spacing: .08em;
}

/* Editorial statement */
.ml-statement {
	display: grid;
	grid-template-columns: minmax(0, 1.35fr) minmax(280px, .65fr);
	gap: clamp(48px, 10vw, 160px);
	align-items: end;
}

.ml-statement__aside {
	padding-left: 28px;
	border-left: 1px solid var(--wd-title-color);
}

.ml-statement__aside p {
	margin: 0 0 24px;
	font-size: 16px;
	line-height: 1.65;
}

.ml-checks {
	display: grid;
	gap: 13px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ml-checks li {
	display: flex;
	gap: 12px;
	align-items: flex-start;
	color: var(--wd-title-color);
	font-weight: 500;
}

.ml-checks li::before {
	flex: 0 0 auto;
	width: 9px;
	height: 9px;
	margin-top: .45em;
	background: var(--wd-alternative-color);
	content: "";
}

/* Category magazine */
.ml-section-head {
	display: flex;
	align-items: end;
	justify-content: space-between;
	gap: 32px;
	margin-bottom: clamp(34px, 5vw, 68px);
}

.ml-text-link {
	display: inline-flex;
	gap: 12px;
	align-items: center;
	min-height: 44px;
	color: var(--wd-title-color);
	font-weight: 600;
}

.ml-text-link:hover {
	color: var(--wd-link-color-hover);
}

.ml-category-grid {
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	grid-auto-rows: 200px;
	gap: 16px;
}

.ml-category-card {
	position: relative;
	grid-column: span 4;
	grid-row: span 2;
	overflow: hidden;
	border-radius: 6px;
	background: var(--wd-title-color);
	color: var(--dof-on-dark);
}

.ml-category-card:first-child {
	grid-column: span 8;
	grid-row: span 3;
}

.ml-category-card:nth-child(4),
.ml-category-card:nth-child(5),
.ml-category-card:nth-child(6) {
	grid-row: span 1;
}

.ml-category-card img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 420ms cubic-bezier(.2,.7,.2,1), opacity 240ms ease;
}

.ml-category-card::after {
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, transparent 30%, rgba(0,0,0,.84));
	content: "";
}

.ml-category-card__body {
	position: absolute;
	z-index: 2;
	right: 0;
	bottom: 0;
	left: 0;
	display: flex;
	align-items: end;
	justify-content: space-between;
	gap: 20px;
	padding: 22px;
}

.ml-category-card__body h3 {
	margin: 0;
	color: var(--dof-on-dark);
	font: 600 clamp(20px, 2vw, 32px)/1.05 var(--wd-title-font);
	letter-spacing: -.03em;
}

.ml-category-card__body span {
	color: var(--wd-alternative-color);
	font-size: 22px;
}

.ml-category-card:hover img {
	transform: scale(1.04);
}

/* Dark production process */
.ml-production {
	background: var(--wd-title-color);
	color: var(--dof-on-dark);
}

.ml-production .ml-title,
.ml-production .ml-kicker {
	color: var(--dof-on-dark);
}

.ml-production .ml-kicker::before {
	background: var(--wd-alternative-color);
}

.ml-process-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	margin-top: clamp(48px, 7vw, 92px);
	border-top: 1px solid rgba(255,255,255,.18);
	border-left: 1px solid rgba(255,255,255,.18);
}

.ml-process-step {
	min-height: 270px;
	padding: 28px;
	border-right: 1px solid rgba(255,255,255,.18);
	border-bottom: 1px solid rgba(255,255,255,.18);
}

.ml-process-step__number {
	display: block;
	margin-bottom: 72px;
	color: var(--wd-alternative-color);
	font: 600 14px/1 var(--wd-text-font);
}

.ml-process-step h3 {
	margin: 0 0 14px;
	color: var(--dof-on-dark);
	font: 600 22px/1.1 var(--wd-title-font);
}

.ml-process-step p {
	margin: 0;
	color: rgba(255,255,255,.62);
	line-height: 1.55;
}

.ml-constructor-callout {
	display: grid;
	grid-template-columns: 1fr auto;
	gap: 32px;
	align-items: center;
	margin-top: 24px;
	padding: clamp(28px, 4vw, 48px);
	background: var(--wd-alternative-color);
	color: var(--wd-title-color);
}

.ml-constructor-callout h3 {
	margin: 0 0 7px;
	color: var(--wd-title-color);
	font: 600 clamp(26px, 3vw, 42px)/1 var(--wd-title-font);
	letter-spacing: -.04em;
}

.ml-constructor-callout p {
	margin: 0;
	color: var(--wd-title-color);
}

/* Technologies as rows, not generic cards */
.ml-tech-list {
	border-top: 1px solid var(--wd-title-color);
}

.ml-tech-row {
	display: grid;
	grid-template-columns: 80px minmax(220px, .7fr) minmax(300px, 1.3fr) 150px;
	gap: 28px;
	align-items: start;
	padding: 28px 24px; /* rows are filled (H-09), so the number and meta need side room */
	border-bottom: 1px solid var(--wd-form-brd-color);
}

.ml-tech-row__number {
	color: var(--wd-link-color-hover);
	font: 600 12px/1.4 var(--wd-text-font);
}

.ml-tech-row h3 {
	margin: 0;
	font: 600 clamp(22px, 2.4vw, 36px)/1 var(--wd-title-font);
	letter-spacing: -.035em;
}

.ml-tech-row p {
	margin: 0;
	line-height: 1.65;
}

.ml-tech-row__meta {
	color: var(--wd-title-color);
	font-size: 13px;
	font-weight: 600;
	text-align: right;
}

/* Case portfolio */
.ml-case-grid {
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	gap: 18px;
}

.ml-case-grid .merch-case-card {
	grid-column: span 4;
	overflow: hidden;
	border: 1px solid var(--wd-form-brd-color);
	border-radius: 6px;
	background: var(--dof-bg-2);
}

.ml-case-grid .merch-case-card:first-child {
	grid-column: span 8;
}

.ml-case-grid .merch-case-card__media {
	aspect-ratio: 16 / 10;
}

.ml-case-grid .merch-case-card:first-child .merch-case-card__media {
	aspect-ratio: 16 / 8.2;
}

.ml-case-grid .merch-case-card__body {
	padding: 24px;
	border-top: 1px solid var(--wd-form-brd-color);
}

.ml-case-grid .merch-case-card__title {
	font-size: clamp(25px, 3vw, 46px);
}

.ml-case-grid .merch-case-card__meta {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 6px;
}

/* Final brief */
.ml-brief {
	background: var(--wd-alternative-color);
	color: var(--wd-title-color);
}

.ml-brief__grid {
	display: grid;
	grid-template-columns: minmax(0, .8fr) minmax(420px, 1.2fr);
	gap: clamp(48px, 9vw, 140px);
	align-items: start;
}

.ml-brief .ml-title,
.ml-brief .ml-lead,
.ml-brief .ml-kicker,
.ml-brief h1,
.ml-brief h2,
.ml-brief h3 {
	color: var(--wd-title-color);
}

.ml-brief .ml-kicker::before {
	background: var(--wd-title-color);
}

.dh-bridge :is(.dh-bridge__eyebrow, h1, h2, h3, p) {
	color: var(--wd-title-color) !important;
}

.ml-brief .merch-form,
.ml-brief .dh-fbox {
	padding: clamp(24px, 4vw, 44px);
	border: 0;
	background: var(--dof-bg-2);
}

/* Inner page hero */
.ml-page-hero {
	position: relative;
	overflow: hidden;
	background: var(--wd-title-color);
	color: var(--dof-on-dark);
}

.ml-page-hero__grid {
	display: grid;
	grid-template-columns: minmax(0, .8fr) minmax(420px, 1.2fr);
	min-height: 620px;
}

.ml-page-hero__copy {
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	padding: clamp(56px, 7vw, 96px) 0;
}

.ml-page-hero .ml-title,
.ml-page-hero .ml-lead {
	color: var(--dof-on-dark);
}

.ml-page-hero .ml-lead {
	margin-top: 28px;
	color: rgba(255,255,255,.68);
}

.ml-page-hero__media {
	position: relative;
	margin-left: clamp(32px, 6vw, 100px);
}

.ml-page-hero__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.ml-page-hero__stamp {
	position: absolute;
	bottom: 24px;
	left: -28px;
	padding: 18px 22px;
	background: var(--wd-alternative-color);
	color: var(--wd-title-color);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .1em;
	text-transform: uppercase;
}

.ml-story-grid {
	display: grid;
	grid-template-columns: minmax(440px, .7fr) minmax(0, 1.3fr);
	gap: clamp(56px, 7vw, 112px);
}

.ml-story-grid__label {
	position: sticky;
	top: 120px;
	align-self: start;
}

.ml-story-grid__label .ml-title {
	max-width: 11ch;
	font-size: clamp(38px, 3.8vw, 60px);
	overflow-wrap: anywhere;
}

.ml-story-grid__content {
	display: grid;
	gap: 34px;
}

.ml-story-grid__content p {
	margin: 0;
	color: var(--wd-title-color);
	font-size: clamp(21px, 2.4vw, 34px);
	line-height: 1.35;
	letter-spacing: -.025em;
}

.ml-principles {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	border-top: 1px solid var(--wd-title-color);
	border-left: 1px solid var(--wd-form-brd-color);
}

.ml-principle {
	min-height: 240px;
	padding: 30px;
	border-right: 1px solid var(--wd-form-brd-color);
	border-bottom: 1px solid var(--wd-form-brd-color);
}

.ml-principle span {
	display: block;
	margin-bottom: 52px;
	color: var(--wd-link-color-hover);
	font-size: 12px;
	font-weight: 600;
}

.ml-principle h3 {
	margin: 0 0 12px;
	font-size: 24px;
}

.ml-principle p {
	margin: 0;
	line-height: 1.6;
}

/* Contacts */
.ml-contact-grid {
	display: grid;
	grid-template-columns: minmax(320px, .7fr) minmax(0, 1.3fr);
	border: 1px solid var(--wd-form-brd-color);
	background: var(--dof-bg-2);
}

.ml-contact-panel,
.ml-contact-form {
	padding: clamp(28px, 5vw, 64px);
}

.ml-contact-panel {
	background: var(--wd-title-color);
	color: var(--dof-on-dark);
}

.ml-contact-panel h2 {
	margin: 0 0 48px;
	color: var(--dof-on-dark);
	font-size: clamp(32px, 4vw, 54px);
}

.ml-contact-item {
	padding: 22px 0;
	border-top: 1px solid rgba(255,255,255,.18);
}

.ml-contact-item span,
.ml-contact-item a {
	display: block;
}

.ml-contact-item span {
	margin-bottom: 8px;
	color: rgba(255,255,255,.5);
	font-size: 11px;
	letter-spacing: .12em;
	text-transform: uppercase;
}

.ml-contact-item a,
.ml-contact-item strong {
	color: var(--dof-on-dark);
	font-size: 18px;
	font-weight: 500;
}

.ml-contact-form .dh-fbox {
	padding: 0;
	border: 0;
	background: transparent;
}

.ml-map {
	overflow: hidden;
	height: 520px;
	margin-top: 24px;
	filter: grayscale(1) contrast(1.08);
}

.ml-map iframe {
	width: 100%;
	height: 100%;
	border: 0;
}

/* WooCommerce becomes a deliberate studio catalogue. */
body.woocommerce.archive .main-page-wrapper {
	padding-top: clamp(48px, 7vw, 96px);
}

body.woocommerce.archive .shop-content-area {
	gap: clamp(28px, 4vw, 56px);
}

body.woocommerce.archive .wd-sidebar {
	padding: 24px;
	border: 1px solid var(--wd-form-brd-color);
	background: var(--dof-bg-2);
}

body.woocommerce.archive .wd-sidebar .woodmart-woocommerce-layered-nav .wd-filter-list {
	display: flex !important;
	flex-direction: column !important;
	flex-wrap: nowrap !important;
	align-items: stretch !important;
	gap: 8px !important;
}

body.woocommerce.archive .wd-sidebar .woodmart-woocommerce-layered-nav .wd-filter-list > li.wc-layered-nav-term {
	display: flex !important;
	align-items: center !important;
	align-self: stretch !important;
	justify-content: flex-start !important;
	width: 100% !important;
	gap: 8px !important;
}

body.woocommerce.archive .wd-sidebar .woodmart-woocommerce-layered-nav .wd-filter-list > li.wc-layered-nav-term > a.layered-nav-link {
	flex: 0 1 auto !important;
	max-width: calc(100% - 40px);
}

body.woocommerce.archive .wd-sidebar .woodmart-woocommerce-layered-nav .wd-filter-list > li.wc-layered-nav-term .wd-filter-lable {
	width: auto !important;
	max-width: 100% !important;
}

body.woocommerce.archive .wd-sidebar .woodmart-woocommerce-layered-nav .wd-filter-list > li.wc-layered-nav-term > .count {
	flex: 0 0 auto;
	margin-top: 0 !important;
}

:is(body.woocommerce.archive, body.single-product) .products.wd-products {
	gap: 36px 18px !important;
	align-items: stretch !important;
	grid-auto-rows: 1fr;
}

:is(body.woocommerce.archive, body.single-product) .wd-product {
	display: flex !important;
	height: 100% !important;
	padding: 0 !important;
	border: 0 !important;
	background: transparent !important;
}

:is(body.woocommerce.archive, body.single-product) .wd-product .wd-product-wrapper {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	width: 100%;
	overflow: hidden;
	border: 1px solid var(--wd-form-brd-color);
	border-radius: 6px;
	background: var(--dof-bg-2);
}

:is(body.woocommerce.archive, body.single-product) .wd-product .product-element-top {
	aspect-ratio: 4 / 5;
	overflow: hidden;
	border-radius: 0;
	background: var(--dof-bg-2);
}

:is(body.woocommerce.archive, body.single-product) .wd-product .product-element-top .product-image-link {
	display: block;
	width: 100%;
	height: 100%;
}

:is(body.woocommerce.archive, body.single-product) .wd-product .product-element-top img {
	width: 100% !important;
	height: 100% !important;
	object-fit: contain !important;
	object-position: center;
}

:is(body.woocommerce.archive, body.single-product) .wd-product .product-wrapper:hover .product-element-top img {
	transform: none !important;
}

:is(body.woocommerce.archive, body.single-product) .wd-product .product-element-bottom {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	padding: 18px !important;
}

:is(body.woocommerce.archive, body.single-product) .wd-product .product-element-bottom::before {
	display: none !important;
	content: none !important;
}

:is(body.woocommerce.archive, body.single-product) .wd-product .wd-entities-title {
	min-height: 2.5em !important;
	font-size: 17px !important;
	line-height: 1.25 !important;
	text-align: left !important;
}

:is(body.woocommerce.archive, body.single-product) .wd-product .price {
	margin-top: 9px !important;
	text-align: left !important;
}

/* Владелец 15.08 (п.3): «В конструктор» с карточек убран — в контейнере снова
   одна кнопка, min-height равен одному токену --ml-btn-h (раньше был calc на
   две кнопки + 8px зазор). */
:is(body.woocommerce.archive, body.single-product) .merch-card-ctas {
	flex-direction: column !important;
	justify-content: flex-end;
	gap: var(--dof-sp-2, 8px) !important;
	min-height: var(--ml-btn-h, 48px);
	margin-top: auto !important;
}

/* Ph14 DEV-03 — catalog card action-area two-state unification (P1). The
   `.merch-card-ctas` container's own min-height + justify-content:flex-end
   already gives the 1-CTA and 2-CTA states IDENTICAL container height and
   consistent bottom-anchored spacing (verified live, unchanged here) -- the
   real drift (14-02-SUMMARY Drift 1, proven RED by 14-06 Task 2 Step 0's
   strengthened qa dev03 assert) was button-INTERNAL box geometry:
   .dof-btn-secondary.merch-cta-constructor computed padding 10 px 12 px vs
   .add_to_cart_button computed padding 12 px 18 px, because dof.css's
   `.woocommerce.archive .wd-product .add_to_cart_button` rule (4 classes,
   !important) out-specified this block's old 1-class selector for that one
   property. Fix: (a) consume the --ml-btn-* token contract (14-03) instead
   of ad-hoc pixel values; (b) add `.wd-product.product-grid-item` (both
   already present on every card's root element, content-product.php
   `$classes` -- zero-PHP fix, no markup touched) to push this selector's
   specificity (0 ids / 5 classes / 1 type) past dof.css's competing rule
   (0 ids / 4 classes / 0 types) so the token values actually win for BOTH
   button classes uniformly.
   Ph14 DEV-16 (14-09): 14-06 originally sized this as the compact
   --ml-btn-h-sm (44 px), anticipating DEV-16 would express catalog as a
   declared "compact surface" exception. DEV-16's actual acceptance gate
   (qa-phase14.js dev16) requires ONE literal height per accent/non-accent
   bucket across ALL SIX surfaces with no size-class split -- so the real
   convergence point is the shared --ml-btn-h (48 px, full), not the sm
   modifier. Switched to full-size; the container rule above grows to match
   (calc() off the same token, not a second magic number) so dev03's
   equal-container-height assert stays satisfied for both card states. */
:is(body.woocommerce.archive, body.single-product) .wd-product.product-grid-item .merch-card-ctas > * {
	display: inline-flex !important;
	flex: 0 0 var(--ml-btn-h);
	align-items: center;
	justify-content: center;
	width: 100%;
	min-width: 0;
	min-height: var(--ml-btn-h) !important;
	padding: var(--ml-btn-pad) !important;
	border-radius: var(--ml-btn-radius) !important;
	font-size: var(--ml-btn-fs) !important;
	font-weight: var(--ml-btn-fw) !important;
	line-height: 1.15 !important;
	letter-spacing: var(--ml-btn-ls) !important;
	text-align: center;
	text-transform: uppercase;
}

/* -- DEV-03/DEV-16 marker scope ends above. The product-page layout rules below
   (site-content/product-image-summary-wrap/product-images/summary-inner/product_title/price)
   predate this phase (2026-07-23, git blame-verified) and are unaudited legacy, per this
   closeout's "phase-added blocks only" scope guard -- not re-swept here. -- */
body.woocommerce.archive select.orderby option {
	background: var(--dof-bg-2) !important;
	color: var(--wd-text-color) !important;
}

body.single-product .site-content {
	padding-top: clamp(40px, 5vw, 72px);
}

body.single-product .product-image-summary-wrap {
	align-items: start;
	gap: clamp(34px, 6vw, 88px);
}

body.single-product .product-images {
	position: sticky;
	top: 104px;
}

body.single-product .summary-inner {
	padding: clamp(24px, 3vw, 42px);
	border: 1px solid var(--wd-form-brd-color);
	border-radius: 6px;
	background: var(--dof-bg-2);
}

body.single-product .product_title {
	font-size: clamp(28px, 2.6vw, 44px) !important;
	line-height: 1.08 !important;
	letter-spacing: -.035em !important;
}

body.single-product .summary-inner > .price {
	margin-top: 18px !important;
	font-size: clamp(24px, 1.8vw, 30px) !important;
	font-weight: 700 !important;
	line-height: 1.15 !important;
}

/* Ph14 DEV-16 (14-09): this was the DECISIVE product-page radius override (0/4/2 specificity,
   beat every dof.css pass) -- previously var(--wd-brd-radius, 5px), a Woodmart theme-option
   fallback, not the button design-system token (14-03 SUMMARY explicitly deferred this exact
   edit to DEV-16 completion). Aligned onto --ml-btn-radius so product converges with the other
   5 surfaces. */
body.single-product form.cart .quantity,
body.single-product form.cart:not(.variations_form) .single_add_to_cart_button,
body.single-product .woocommerce-variation-add-to-cart .single_add_to_cart_button,
body.single-product .merch-cta-block .merch-cta-primary,
body.single-product .merch-cta-block .merch-cta-secondary {
	border-radius: var(--ml-btn-radius, 2px) !important;
}

body.single-product form.cart:not(.variations_form) .single_add_to_cart_button,
body.single-product .woocommerce-variation-add-to-cart .single_add_to_cart_button,
body.single-product .merch-cta-block .merch-cta-primary,
body.single-product .merch-cta-block .merch-cta-secondary {
	font-size: var(--ml-btn-fs, 11px) !important;
	font-weight: var(--ml-btn-fw, 600) !important;
	letter-spacing: var(--ml-btn-ls, .14em) !important;
}

/* -- DEV-16 marker scope ends above. The short-description/woocommerce-tabs rules below
   predate this phase (2026-07-23, git blame-verified) and are unaudited legacy, per this
   closeout's "phase-added blocks only" scope guard -- not re-swept here. -- */
body.single-product .woocommerce-product-details__short-description {
	font-size: 17px;
	line-height: 1.65;
}

body.single-product .woocommerce-tabs {
	margin-top: clamp(64px, 8vw, 120px);
}

/* Account / cart / checkout: app-like working areas. */
body.woocommerce-account,
body.woocommerce-cart,
body.woocommerce-checkout {
	background:
		linear-gradient(90deg, color-mix(in srgb, var(--wd-form-brd-color) 35%, transparent) 1px, transparent 1px) 0 0 / 72px 72px,
		var(--wd-main-bgcolor, #fdf6e3);
}

/* Brief page: one focused editorial canvas instead of the old boxed form. */
.merch-request.ml-site {
	display: grid;
	grid-template-columns: minmax(360px, .72fr) minmax(620px, 1.28fr);
	width: min(calc(100% - 64px), 1440px);
	max-width: 1440px;
	margin: clamp(40px, 5vw, 80px) auto;
	padding: 0;
	border: 1px solid var(--wd-form-brd-color);
	background: var(--dof-bg-2);
}

.merch-request__intro {
	display: flex;
	flex-direction: column;
	justify-content: flex-start;
	min-height: 620px;
	margin: 0;
	padding: clamp(36px, 5vw, 72px);
	background: var(--wd-title-color);
	color: rgba(255,255,255,.72);
}

.merch-request__eyebrow {
	color: var(--wd-alternative-color);
	font: 600 11px/1.2 var(--wd-text-font);
	letter-spacing: .18em;
	text-transform: uppercase;
}

/* Ph-remainder DEV-17 -- request-page H1 previously ran its OWN third one-off clamp
   (50px,6vw,92px), a hand-tuned formula independent of both .ml-display (home/contacts/cases)
   and .ml-title (about/technologies) -- one of six distinct H1 sizes this audit MEASURED live
   at 1280px. Consumed onto the shared .ml-display hero-tier token here instead so this page's
   H1 tracks the SAME formula as the site's other full-bleed hero H1s rather than drifting on
   its own; layout-specific properties (max-width/margin/color for the dark split panel) are
   untouched. */
/* Владелец 15.08 (п.1): hero-формула .ml-display (7.2vw/116px) не влезала в
   тёмную панель ~440px минус padding — «Розкажіть,» обрезался. Размер этого H1
   диктуется шириной панели, а не общесайтовым hero-токеном. */
.merch-request__intro h1 {
	max-width: 9ch;
	margin: clamp(110px, 17vh, 180px) 0 28px;
	color: var(--dof-on-dark);
	font-size: clamp(40px, 4.4vw, 64px);
	line-height: .9;
	letter-spacing: -.065em;
	text-wrap: balance;
}

.merch-request__intro > p:last-child {
	max-width: 36ch;
	margin: 0;
	font-size: 17px;
	line-height: 1.65;
}

.merch-request__form {
	display: flex;
	align-items: center;
	padding: clamp(40px, 5vw, 80px);
	background: var(--dof-bg-2);
}

.merch-request__form .merch-form {
	width: 100%;
	padding: 0;
	border: 0;
	background: transparent;
}

body.merch-request-page .main-page-wrapper {
	background: var(--wd-main-bgcolor, #fdf6e3);
}

/* All lead forms use the same clear contact-form language. */
.ml-site :is(.merch-form__field > span, .dh-flbl) {
	display: block;
	margin-bottom: 8px;
	color: var(--wd-text-color);
	font-size: 11px;
	font-weight: 500;
	letter-spacing: .14em;
	text-transform: uppercase;
}

.ml-site :is(.merch-form input, .merch-form select, .merch-form textarea, .dh-finp, .dh-fsel, .dh-ftxt) {
	width: 100%;
	margin: 0;
	padding: 14px 16px;
	border: 1px solid var(--dof-line-strong);
	border-radius: 6px;
	background: var(--dof-bg-2);
	color: var(--wd-text-color);
	font: 400 15px/1.4 var(--wd-text-font);
	box-shadow: none;
}

.ml-site :is(.merch-form input, .merch-form select, .dh-finp, .dh-fsel) {
	min-height: 44px;
}

.ml-site :is(.merch-form textarea, .dh-ftxt) {
	min-height: 140px;
	resize: vertical;
}

.ml-site :is(.merch-form input, .merch-form select, .merch-form textarea, .dh-finp, .dh-fsel, .dh-ftxt):focus {
	border-color: var(--wd-title-color);
	background: var(--dof-bg-2);
	outline: 2px solid var(--wd-alternative-color);
	outline-offset: 1px;
}

/* Ph14 DEV-16 (14-09): geometry/typography aliased onto the canonical --ml-btn-* contract
   (14-03) -- request-form submit (/request/) converges with home/product/cart/checkout;
   color/hover semantics untouched. */
.ml-site :is(.merch-form__submit, .dh-fsub) {
	width: 100%;
	min-height: var(--ml-btn-h, 48px);
	margin-top: 22px; /* one-off: pre-existing spacing above the request-form submit button, between --dof-sp-5(24) and --dof-sp-4(16) -- no exact rung, kept at its original measured value */
	padding: var(--ml-btn-pad, 16px 24px);
	border: 0;
	border-radius: var(--ml-btn-radius, 2px);
	background: var(--wd-alternative-color);
	color: var(--wd-title-color);
	font-size: var(--ml-btn-fs, 11px);
	font-weight: var(--ml-btn-fw, 600);
	letter-spacing: var(--ml-btn-ls, .14em);
	text-transform: uppercase;
}

.ml-site :is(.merch-form__submit, .dh-fsub):hover {
	background: var(--wd-title-color);
	color: var(--dof-on-dark);
}

/* -- DEV-16 marker scope ends above. The rules below (account nav/content, product-card
   hover-motion, .ml-reveal) predate this phase (2026-07-23, git blame-verified) and are
   unaudited legacy, per this closeout's "phase-added blocks only" scope guard -- not
   re-swept here. -- */
.ml-site .merch-form__error:empty {
	display: none;
}

body.woocommerce-account .wd-my-account-wrapper,
body.woocommerce-cart .woocommerce,
body.woocommerce-checkout .woocommerce {
	width: min(calc(100% - 48px), var(--wd-container-w));
	margin-inline: auto;
}

body.woocommerce-account .woocommerce-MyAccount-navigation {
	padding: 22px;
	border: 1px solid var(--wd-form-brd-color);
	background: var(--wd-title-color);
}

body.woocommerce-account .woocommerce-MyAccount-navigation a {
	color: rgba(255,255,255,.72) !important;
}

body.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a {
	background: var(--wd-alternative-color);
	color: var(--wd-title-color) !important;
	box-shadow: none;
}

body.woocommerce-account .woocommerce-MyAccount-content {
	border: 0;
	border-radius: 6px;
	background: var(--dof-bg-2);
	box-shadow: 0 24px 80px rgba(0,0,0,.07);
}

/* Ph14 DEV-16 (14-09): this sitewide radius reset was a 4th, previously-undiscovered
   contributor to the radius drift RESEARCH Pitfall 5 describes (it lives here, not in
   dof.css's three named passes) -- e.g. it was the decisive winner for cart's
   .checkout-button (radius 6 px) until this edit. Aligned onto --ml-btn-radius; .merch-card-
   ctas > * is already overridden to the same token by the higher-specificity 14-06 catalog-
   card rule above, so this is a harmless no-op there, kept for the other selectors' sake. */
.ml-site .button,
.ml-site button,
.ml-site input[type="submit"],
.merch-card-ctas > *,
.woocommerce-account .button,
.woocommerce-cart .button,
.woocommerce-checkout .button,
.dof-footer__cta {
	border-radius: var(--ml-btn-radius, 2px) !important;
}

/* -- DEV-16 marker scope ends above. The hover-motion/.ml-reveal rules below predate this
   phase (2026-07-23, git blame-verified) and are unaudited legacy, per this closeout's
   "phase-added blocks only" scope guard -- not re-swept here. -- */
.ml-arrow,
.ml-text-link [aria-hidden="true"],
.merch-case-card__action [aria-hidden="true"],
.ml-category-card__body [aria-hidden="true"] {
	display: inline-block;
	transition: transform 180ms ease;
}

.ml-button:hover .ml-arrow,
.ml-text-link:hover [aria-hidden="true"],
.merch-case-card:hover .merch-case-card__action [aria-hidden="true"] {
	transform: translateX(5px);
}

.ml-category-card:hover .ml-category-card__body [aria-hidden="true"] {
	transform: translate(3px, -3px);
}

.ml-process-step,
.ml-tech-row {
	transition: background-color 220ms ease, transform 220ms ease;
}

.ml-process-step:hover {
	background: rgba(255,255,255,.045);
	transform: translateY(-4px);
}

.ml-process-step__number {
	transition: transform 220ms ease;
}

.ml-process-step:hover .ml-process-step__number {
	transform: translateX(6px);
}

.ml-tech-row:hover {
	background: color-mix(in srgb, var(--wd-alternative-color) 7%, transparent);
}

.ml-reveal {
	opacity: 0;
	transform: translateY(24px);
	transition: opacity 520ms ease var(--ml-reveal-delay, 0ms), transform 520ms cubic-bezier(.2,.7,.2,1) var(--ml-reveal-delay, 0ms);
}

.ml-reveal.is-visible {
	opacity: 1;
	transform: none;
}

/* Shared old pages get new rhythm even before custom markup. */
body.page-template-template-privacy .dh-page-content-main,
body.page-template-template-oplata .dh-page-content-main,
body.page-template-template-povernennia .dh-page-content-main,
body.page-template-template-umovy .dh-page-content-main {
	width: min(calc(100% - 48px), var(--wd-container-w));
	margin-inline: auto;
	padding-block: clamp(56px, 8vw, 112px);
}

@media (max-width: 1024px) {
	.ml-home-hero__grid,
	.ml-page-hero__grid,
	.ml-brief__grid {
		grid-template-columns: 1fr;
	}

	.ml-home-hero__copy {
		order: 2;
	}

	.ml-home-hero__media {
		min-height: 52svh;
	}

	.ml-page-hero__media {
		min-height: 460px;
		margin-left: 40px;
	}

	.ml-proofbar__grid,
	.ml-process-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.ml-category-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		grid-auto-rows: 250px;
	}

	.ml-category-card,
	.ml-category-card:first-child,
	.ml-category-card:nth-child(n) {
		grid-column: auto;
		grid-row: auto;
	}

	.ml-category-card:first-child {
		grid-column: span 2;
	}

	.ml-tech-row {
		grid-template-columns: 56px minmax(180px, .6fr) minmax(0, 1.4fr);
	}

	.ml-tech-row__meta {
		grid-column: 2 / -1;
		text-align: left;
	}

	.ml-case-grid .merch-case-card,
	.ml-case-grid .merch-case-card:first-child {
		grid-column: span 6;
	}

	.ml-contact-grid {
		grid-template-columns: 1fr;
	}

	.ml-story-grid {
		grid-template-columns: 1fr;
		gap: 40px;
	}

	.ml-story-grid__label {
		position: static;
	}
}

@media (max-width: 767px) {
	.ml-shell {
		width: min(calc(100% - 32px), var(--wd-container-w));
	}

	.merch-request.ml-site {
		display: block;
		width: calc(100% - 24px);
		margin: 24px auto 48px;
	}

	.merch-request__intro {
		min-height: 330px;
		padding: 28px 24px;
	}

	.merch-request__intro h1 {
		margin: 64px 0 20px;
	}

	.merch-request__form {
		display: block;
		padding: 28px 20px;
	}

	.ml-section {
		padding-block: 72px;
	}

	body:not(.lumise-editor-page) .whb-general-header {
		height: 64px !important;
	}

	.ml-home-hero {
		min-height: calc(100svh - 64px);
	}

	.ml-home-hero__grid {
		position: relative;
		display: block;
		min-height: calc(100svh - 64px);
	}

	.ml-home-hero__media {
		position: absolute;
		inset: 0;
		min-height: 0;
	}

	.ml-home-hero__media::after {
		background: linear-gradient(180deg, color-mix(in srgb, var(--dof-ink) 12%, transparent) 8%, color-mix(in srgb, var(--dof-ink) 92%, transparent) 72%, var(--dof-surface-dark) 100%);
	}

	.ml-home-hero__copy {
		min-height: calc(100svh - 64px);
		padding: 180px 16px max(82px, calc(72px + env(safe-area-inset-bottom)));
		background: transparent;
	}

	.ml-home-hero__copy .ml-display {
		max-width: 10ch;
		font-size: clamp(42px, 12vw, 54px);
		line-height: .92;
	}

	.ml-home-hero__copy .ml-lead {
		margin-top: 18px;
		font-size: 15px;
		line-height: 1.45;
	}

	.ml-home-hero__actions {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 8px;
		margin-top: 22px;
	}

	.ml-home-hero__actions .ml-button {
		width: 100%;
		min-height: 48px;
		padding: 12px 10px;
		font-size: 10px;
		text-align: center;
	}

	.ml-home-hero__note {
		display: none;
	}

	.ml-proofbar__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.ml-proofbar__item:nth-child(2) {
		border-right: 0;
	}

	.ml-proofbar__item:nth-child(-n+2) {
		border-bottom: 1px solid var(--wd-form-brd-color);
	}

	.ml-statement,
	.ml-story-grid {
		grid-template-columns: 1fr;
		gap: 40px;
	}

	.ml-story-grid__label {
		position: static;
	}

	.ml-section-head {
		display: grid;
	}

	.ml-category-grid {
		grid-template-columns: 1fr;
		grid-auto-rows: 300px;
	}

	.ml-category-card:first-child {
		grid-column: auto;
	}

	.ml-process-grid {
		grid-template-columns: 1fr;
	}

	.ml-process-step {
		min-height: 220px;
	}

	.ml-process-step__number {
		margin-bottom: 48px;
	}

	.ml-constructor-callout {
		grid-template-columns: 1fr;
	}

	.ml-tech-row {
		grid-template-columns: 42px minmax(0, 1fr);
		gap: 14px;
		padding: 20px 16px;
	}

	/* Everything but the number goes to the text column: the case "Що зробили" body is a div, not a p. */
	.ml-tech-row > :not(.ml-tech-row__number) {
		grid-column: 2;
	}

	.ml-case-grid {
		grid-template-columns: 1fr;
	}

	.ml-case-grid .merch-case-card,
	.ml-case-grid .merch-case-card:first-child {
		grid-column: auto;
	}

	.ml-page-hero__grid {
		min-height: auto;
	}

	.ml-page-hero__copy {
		order: 2;
		padding: 48px 0 64px;
	}

	.ml-page-hero__media {
		min-height: 420px;
		margin-left: 0;
	}

	.ml-page-hero__stamp {
		left: 16px;
	}

	.ml-principles {
		grid-template-columns: 1fr;
	}

	.ml-contact-panel,
	.ml-contact-form {
		padding: 28px 20px;
	}

	:is(body.woocommerce.archive, body.single-product) .products.wd-products {
		gap: 24px 16px !important;
	}

	:is(body.woocommerce.archive, body.single-product) .wd-product .wd-product-wrapper {
		gap: 8px !important;
		padding: 8px !important;
	}

	:is(body.woocommerce.archive, body.single-product) .merch-card-ctas {
		width: 100% !important;
		min-height: 100px;
		padding: 0 !important;
	}

	:is(body.woocommerce.archive, body.single-product) .wd-product .product-element-bottom {
		gap: 4px !important;
		padding: 0 !important;
	}

	:is(body.woocommerce.archive, body.single-product) .wd-product .wd-entities-title {
		min-height: 2.6em !important;
		max-height: 2.6em !important;
		margin: 0 !important;
		font-size: 14px !important;
		line-height: 1.3 !important;
	}

	:is(body.woocommerce.archive, body.single-product) .wd-product .price {
		margin: 2px 0 0 !important;
	}

	:is(body.woocommerce.archive, body.single-product) .merch-card-ctas > * {
		width: 100% !important;
		margin-inline: 0 !important;
	}

	body.single-product .product-images {
		position: relative !important;
		top: auto !important;
	}

	body.single-product .summary-inner {
		padding: 22px 16px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.ml-reveal {
		opacity: 1;
		transform: none;
		transition: none;
	}
}

/* Fixed WooCommerce box catalogue: uses the WoodMart visual variables above. */
.ml-box-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.ml-box-card { display: flex; flex-direction: column; overflow: hidden; border: 1px solid var(--wd-form-brd-color); border-radius: 6px; background: var(--wd-main-bgcolor, #faeec6); }
.ml-box-card__media { display: block; aspect-ratio: 4 / 3; overflow: hidden; background: var(--dof-bg-2); }
.ml-box-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 220ms ease; }
.ml-box-card:hover .ml-box-card__media img { transform: scale(1.025); }
.ml-box-card__body { display: flex; flex: 1; flex-direction: column; align-items: flex-start; padding: 24px; }
.ml-box-card__body h3 { margin: 0 0 10px; font-size: clamp(22px, 2vw, 30px); line-height: 1.08; }
.ml-box-card__body h3 a { color: var(--wd-title-color); }
.ml-box-card__body p { margin: 0 0 18px; color: var(--wd-text-color); line-height: 1.55; }
.ml-box-card__body strong { color: var(--wd-title-color); font-size: 18px; }
.ml-box-card__price { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; }
.ml-box-card__price del, .ml-box-details del { color: var(--wd-text-color); font-size: .82em; font-weight: 500; }
.ml-box-card__price ins, .ml-box-details ins { color: var(--wd-title-color); background: transparent; text-decoration: none; }
.ml-box-card__price > span { font-size: .78em; font-weight: 500; }
.ml-box-card__body > span { margin-top: 6px; color: var(--wd-text-color); font-size: 13px; }
.ml-box-card__body .ml-button { width: 100%; min-height: 44px; margin-top: auto; text-align: center; }
.ml-box-cta { margin-top: 28px; text-align: center; }
.ml-box-empty { padding: 28px; border: 1px solid var(--wd-form-brd-color); }
.ml-box-details { margin: 24px 0; padding: 22px; border: 1px solid var(--wd-form-brd-color); background: var(--wd-main-bgcolor, #faeec6); }
.ml-box-details h2 { margin: 0 0 12px; font-size: 18px; }
.ml-box-details ul { margin: 0 0 20px; padding-left: 20px; }
.ml-box-details table { width: 100%; margin-bottom: 16px; border-collapse: collapse; }
.ml-box-details th, .ml-box-details td { padding: 9px 0; border-bottom: 1px solid var(--wd-form-brd-color); text-align: left; }
.ml-box-details td { text-align: right; }
/* DEV-06 -- box page renders TWO yellow buttons (MEASURED live, box 50322: both
   .single_add_to_cart_button AND .ml-box-sample computed background rgb(243,227,25)) because
   .ml-box-sample also carries WooCommerce's own `button alt` class, which dof.css's :where()
   primary sweep (~L10148, zero specificity but !important) fills accent-yellow by default.
   Demoted to the site's secondary style (outline, ink border/text, ink-fill on hover) so
   "Замовити зразок" stops competing with "Додати на прорахунок" for the one primary action --
   this plain class selector (0,1,0) beats the :where() sweep's 0 specificity even though both
   sides use !important. DEV-16: typography brought onto the --ml-btn-* token contract (was
   13px, non-uppercase, no letter-spacing -- MEASURED live) so it reads as the same button
   FAMILY as every other CTA, just in the secondary/compact size (--ml-btn-h-sm, already
   matched at 44px). */
/* DEV-16 leftover (orchestrator, 2026-08-13): the sample button sat on the
   small token, 44px, directly under a 48px primary — the one control on the
   box page still off the shared scale. Same token as every other full-width
   action now; the secondary reading comes from the transparent fill, not
   from being shorter than its neighbour. */
.ml-box-sample {
	width: 100%;
	/* !important because dof.css's `.woocommerce button.button { min-height: 44px }`
	   (0,2,1) outranks this class selector — MEASURED: computed min-height stayed
	   44px until this line. */
	min-height: var(--ml-btn-h, 48px) !important;
	height: var(--ml-btn-h, 48px) !important;
	margin: 12px 0;
	background: transparent !important;
	border: 1px solid var(--wd-title-color) !important;
	color: var(--wd-title-color) !important;
	font-size: var(--ml-btn-fs, 11px) !important;
	font-weight: var(--ml-btn-fw, 600) !important;
	letter-spacing: var(--ml-btn-ls, .14em) !important;
	text-transform: uppercase;
}
.ml-box-sample:hover,
.ml-box-sample:focus-visible {
	border-color: var(--wd-title-color) !important;
	background: var(--wd-title-color) !important;
	color: var(--dof-on-dark) !important;
}
.ml-box-sample .woocommerce-Price-amount, .ml-box-sample .woocommerce-Price-currencySymbol { color: inherit !important; }
.ml-box-details + form.cart { margin-top: 20px; }
.ml-box-card a:focus-visible, .ml-box-page a:focus-visible, .ml-box-sample:focus-visible { outline: 3px solid var(--wd-alternative-color); outline-offset: 3px; }
@media (max-width: 767px) { .ml-box-grid { grid-template-columns: 1fr; } .ml-box-card__body { padding: 20px; } .ml-box-card__body .ml-button { min-height: 48px; } }

@media (prefers-reduced-motion: reduce) {
	.ml-site *,
	.ml-site *::before,
	.ml-site *::after {
		scroll-behavior: auto !important;
		transition-duration: .01ms !important;
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
	}
}

.ml-cultural-brief__head,
.ml-moments__head {
	max-width: 880px;
	margin-bottom: 40px;
}

.ml-cultural-brief__rows,
.ml-moments__grid {
	margin: 0;
}

.ml-cultural-brief__rows {
	width: 100%;
	border: 0;
	border-collapse: collapse;
}

.ml-cultural-brief__row {
	display: grid;
	grid-template-columns: minmax(180px, .7fr) minmax(0, 1.3fr);
	gap: 24px;
	min-width: 0;
	padding: 24px 0;
	border-top: 1px solid var(--wd-form-brd-color);
}

.ml-cultural-brief__rows tbody .ml-cultural-brief__row:last-child {
	border-bottom: 1px solid var(--wd-form-brd-color);
}

.ml-cultural-brief__row th,
.ml-cultural-brief__row td,
.ml-moments__item dt,
.ml-moments__item dd {
	min-width: 0;
	margin: 0;
	padding: 0;
	border: 0;
	text-align: left;
	overflow-wrap: anywhere;
}

.ml-cultural-brief__row th,
.ml-moments__item dt {
	color: var(--wd-title-color);
	font-weight: 700;
}

.ml-cultural-brief__columns {
	padding-top: 0;
	padding-bottom: 12px;
	border-top: 0;
}

.ml-cultural-brief__columns th {
	color: var(--wd-primary-color);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
}

.ml-moments__grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 20px;
}

.ml-moments__item {
	min-width: 0;
	padding: 24px;
	border: 1px solid var(--wd-form-brd-color);
	background: var(--wd-main-bgcolor, #faeec6);
}

.ml-moments__item dd {
	margin-top: 12px;
	color: var(--wd-text-color);
}

@media (max-width: 767px) {
	.ml-cultural-brief__head,
	.ml-moments__head {
		margin-bottom: 28px;
	}

	.ml-moments__grid {
		grid-template-columns: 1fr;
	}

	.ml-cultural-brief__row {
		grid-template-columns: minmax(110px, .7fr) minmax(0, 1.3fr);
		gap: 12px;
	}
}

/* ══════════════════════════════════════════════════════════════════
   ML BUTTON SYSTEM — canonical variant contract (DEV-06 foundation;
   DEV-16 completes the sitewide rollout in wave 6/P2). Declares the FULL
   contract (height/padding/radius/typography/focus/disabled/loading) in
   ONE pass per RESEARCH Pitfall 5: three earlier incremental dof.css
   button passes (~L1953, ~L3089, ~L10012) each only patched a subset of
   properties and never converged on one radius value (0/2/5/6px still
   drift across the site). This system exists so every later wave
   consumes ONE token/class source instead of adding a fourth partial
   pass. Phase 14-03, 2026-08-09.
   ══════════════════════════════════════════════════════════════════ */
/* TOKEN-MAP CONTRACT (DEV-17 T2 closeout, 14-10, 2026-08-09) — read this before adding a new
   button/icon/spacing value anywhere in dof.css or merchlab-studio.css.
   ---------------------------------------------------------------------------------------
   --ml-btn-h        48px   min-height, default/primary/secondary size (ALL 6 tested surfaces
                             converge here per DEV-16 -- 14-09 removed the one compact-size
                             exception catalog cards used to have; there is no other sanctioned
                             button height sitewide).
   --ml-btn-h-sm     44px   min-height, .ml-btn--sm modifier only (drawer CTA/utility rows).
   --ml-btn-pad      16px 24px   default padding.
   --ml-btn-pad-sm   10px 16px   .ml-btn--sm padding.
   --ml-btn-radius   2px    single sitewide button/form-control radius (replaces the 0/2/5/6px
                             drift RESEARCH Pitfall 5 documented -- see comment above).
   --ml-btn-fs       11px   button label font-size.
   --ml-btn-ls       .14em  button label letter-spacing.
   --ml-btn-fw       600    button label font-weight.
   --ml-btn-focus-ring       double-ring box-shadow, see comment below.
   --dof-icon-sm/md/lg   14/18/24px   inline glyph scale (dof.css :root, DEV-17 T2) -- --dof-icon-md
                             is wired to .ml-arrow (the button CTA arrow); sm/lg are forward rungs
                             for the next icon surface (toolbar/drawer/chip) that needs a size.
   --dof-sp-1..10    dof.css's harmonic spacing ladder (4/8/12/16/24/40/64/96/140/200px) -- reuse
                             THIS for any new gap/margin/padding value before hardcoding a number;
                             this closeout's sweep used it for card-CTA/drawer gaps and insets.
   USAGE RULE: any new button, icon, or spacing value in a Phase-14-or-later block consumes one
   of the rungs above (or dof.css's --dof-fs-* and --dof-sp-* general ladders) via var(...). A value
   that genuinely has no matching rung (a live-measured one-off: a clamp ceiling, a specific
   safe-area calc, a decorative shadow/hover-transform) stays a literal px with an inline
   trailing comment containing the word one-off, explaining the measurement -- do not invent
   a new token for a single unrepeated number. Extend this contract, don't fork it (RESEARCH Pitfall 5 is the
   fourth-partial-pass failure mode this exists to prevent). */
:root {
	--ml-btn-h: 48px; /* min-height, default/primary size */
	--ml-btn-h-sm: 44px; /* min-height, .ml-btn--sm modifier — the ONLY sanctioned way to go compact */
	--ml-btn-pad: 16px 24px;
	--ml-btn-pad-sm: 10px 16px;
	/* Single sitewide radius value — matches dof.css's own broad :where(...)
	   form-control sweep (~L10012: border-radius:2px !important on
	   .dh-btn-p/.single_add_to_cart_button et al.), NOT the product-page
	   local 5px override (merchlab-studio.css body.single-product scope,
	   pre-existing at ~L1084, out of this plan's scope — untouched here). */
	--ml-btn-radius: 2px;
	--ml-btn-fs: 11px;
	--ml-btn-ls: .14em;
	--ml-btn-fw: 600;
	/* Double-ring focus indicator: a single flat color cannot clear WCAG
	   1.4.11's 3:1 non-text contrast on BOTH a light (var(--dof-bg-2)) and a dark
	   (var(--dof-ink)) section at once — measured live: --dof-accent (var(--dof-accent)) is
	   ~1.1:1 against var(--dof-bg-2) (fails), --dof-ink (var(--dof-ink)) is ~1.05:1 against
	   var(--dof-ink) (fails). The white ring reads on dark sections (~19:1 on
	   var(--dof-ink)); the ink ring reads on light sections (~15:1 on #f2f2ef) —
	   together at least one ring segment clears 3:1 in every context. */
	--ml-btn-focus-ring: 0 0 0 2px var(--dof-bg, #faeec6), 0 0 0 4px var(--dof-ink, #12263b);
}

.ml-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	box-sizing: border-box;
	min-height: var(--ml-btn-h);
	padding: var(--ml-btn-pad);
	border: 1px solid transparent;
	border-radius: var(--ml-btn-radius);
	font-family: inherit;
	font-size: var(--ml-btn-fs);
	font-weight: var(--ml-btn-fw);
	line-height: 1.2;
	letter-spacing: var(--ml-btn-ls);
	text-transform: uppercase;
	text-decoration: none;
	cursor: pointer;
	transition: background 200ms ease, color 200ms ease, border-color 200ms ease, opacity 200ms ease;
}

.ml-btn--sm {
	min-height: var(--ml-btn-h-sm);
	padding: var(--ml-btn-pad-sm);
}

/* Primary — the ONE accent-bg button on a given surface. */
.ml-btn--primary {
	background: var(--dof-accent, #ffe786);
	border-color: var(--dof-accent, #ffe786);
	color: var(--dof-ink, #12263b);
}
.ml-btn--primary:hover,
.ml-btn--primary:focus-visible {
	background: var(--dof-accent-dk, #f0d65a);
	border-color: var(--dof-accent-dk, #f0d65a);
}

/* Secondary — outline, ink border/text, no fill. */
.ml-btn--secondary {
	background: transparent;
	border-color: var(--dof-ink, #12263b);
	color: var(--dof-ink, #12263b);
}
.ml-btn--secondary:hover,
.ml-btn--secondary:focus-visible {
	background: var(--dof-ink, #12263b);
	color: var(--dof-on-dark);
}
/* No sitewide dark-mode toggle exists in this codebase today — .ml-on-dark
   is a manual per-placement modifier a later wave applies directly to a
   button instance sitting on a dark-background section (mirrors dof.css's
   own per-component dark-context classes, e.g. .dof-footer__cta, rather
   than inventing an unused global dark-mode class). */
.ml-btn--secondary.ml-on-dark {
	border-color: var(--dof-bg-2);
	color: var(--dof-on-dark);
}
.ml-btn--secondary.ml-on-dark:hover,
.ml-btn--secondary.ml-on-dark:focus-visible {
	background: var(--dof-bg-2);
	color: var(--dof-ink, #12263b);
}

/* Tertiary — text-link affordance, no box; min-height kept for the touch
   target even though there's no visible button chrome. */
.ml-btn--tertiary {
	min-height: 44px;
	padding: 0;
	border: none;
	background: transparent;
	color: var(--dof-ink, #12263b);
	text-decoration: underline;
	text-underline-offset: 3px;
}
.ml-btn--tertiary:hover,
.ml-btn--tertiary:focus-visible {
	color: var(--dof-accent-dk, #f0d65a);
}

.ml-btn:focus-visible {
	outline: none;
	box-shadow: var(--ml-btn-focus-ring);
}

.ml-btn:disabled,
.ml-btn[aria-disabled="true"] {
	opacity: .5;
	cursor: not-allowed;
	pointer-events: none;
}

.ml-btn.is-loading {
	position: relative;
	color: transparent !important;
	pointer-events: none;
}
.ml-btn.is-loading::before {
	position: absolute;
	inset: 0;
	margin: auto;
	width: 16px;
	height: 16px;
	border: 2px solid currentColor;
	border-top-color: transparent;
	border-radius: 50%;
	color: var(--dof-ink, #12263b);
	content: "";
	animation: ml-btn-spin 700ms linear infinite;
}
@keyframes ml-btn-spin {
	to { transform: rotate(360deg); }
}

/* Product-page application (DEV-06): the native add-to-cart submit is
   ALREADY the page's one accent-bg CTA and already satisfies the primary
   contract via existing high-specificity dof.css rules (~L9919
   form.cart:not(.variations_form) .single_add_to_cart_button, reinforced
   by ~L10011's :where() pass): 48px height, accent bg, ink text. Not
   re-declared here — two competing !important sources on one element is
   exactly Pitfall 5's failure mode. This comment is the "map to primary"
   record the plan asks for.
   Constructor CTA (Task 2 markup: .merch-cta-constructor) steps back to
   secondary/outline; sample CTA (Task 2 markup: .merch-cta-sample) steps
   back to tertiary/link — closes the "class NAME merch-cta-primary is
   legacy, visual primary moved to add-to-cart" mismatch RESEARCH flagged.
   !important is required below because .dh-btn-p/.dh-btn-g's own
   background/border/color (dof.css ~L3115-3146) is !important with real
   (non-:where) specificity and stays present on these anchors for
   back-compat (kept per plan). This stylesheet loads AFTER dof.css
   (dof-init.php enqueue deps) and every selector below carries HIGHER
   specificity (body.single-product + 3 classes vs. dof.css's plain
   .dh-btn-p/.dh-btn-g single-class selectors) — ties resolve here on
   specificity, not merely source order (verified via specificity math). */
body.single-product .merch-cta-block .merch-cta-constructor.ml-btn--secondary {
	background: transparent !important;
	border: 1px solid var(--dof-ink, #12263b) !important;
	color: var(--dof-ink, #12263b) !important;
}
body.single-product .merch-cta-block .merch-cta-constructor.ml-btn--secondary:hover,
body.single-product .merch-cta-block .merch-cta-constructor.ml-btn--secondary:focus-visible {
	background: var(--dof-ink, #12263b) !important;
	color: var(--dof-on-dark) !important;
}
body.single-product .merchlab-constructor-cta {
	margin-top: 12px;
}
body.single-product .merchlab-constructor-cta .merch-cta-constructor {
	min-height: 44px !important;
}
body.single-product .merch-cta-block .merch-cta-sample.ml-btn--tertiary {
	background: transparent !important;
	border: none !important;
	min-height: var(--ml-btn-h-sm, 44px) !important;
	padding: 0 !important;
	color: var(--dof-ink, #12263b) !important;
	text-decoration: underline !important;
}
body.single-product .merch-cta-block .merch-cta-sample.ml-btn--tertiary:hover,
body.single-product .merch-cta-block .merch-cta-sample.ml-btn--tertiary:focus-visible {
	color: var(--dof-accent-dk, #f0d65a) !important;
}

/* Ph14 DEV-16 completion (14-09) -- cart proceed-to-checkout + checkout place_order geometry
   onto the --ml-btn-* contract. Both are native WC markup (no .ml-btn class reachable without
   a template touch). Root cause of their prior drift: dof.css's own per-page rules
   (.woocommerce-cart .wc-proceed-to-checkout .checkout-button padding:16 px 28 px;
   .woocommerce-checkout #place_order padding:18 px 28 px + height:auto !important, both non-
   :where()) drove NATURAL (unconstrained) box heights of 45/49 px that the min-height:48 px
   from dof.css's :where() sweep (zero specificity) could never enforce. Forcing --ml-btn-pad
   here brings natural content height under 48 px so min-height then actually takes effect
   (place_order's own height:auto !important is a DIFFERENT property and coexists fine with
   min-height per the CSS box model -- no need to touch dof.css's rule). Specificity
   (body+2/3 classes, body+class+ID) exceeds the rules being replaced regardless of file
   order; color/hover/border semantics of both buttons are untouched. */
body.woocommerce-cart .wc-proceed-to-checkout .checkout-button {
	padding: var(--ml-btn-pad, 16px 24px) !important;
	min-height: var(--ml-btn-h, 48px) !important;
	border-radius: var(--ml-btn-radius, 2px) !important;
	letter-spacing: var(--ml-btn-ls, .14em) !important;
}
body.woocommerce-checkout #place_order {
	padding: var(--ml-btn-pad, 16px 24px) !important;
	min-height: var(--ml-btn-h, 48px) !important;
	border-radius: var(--ml-btn-radius, 2px) !important;
	letter-spacing: var(--ml-btn-ls, .14em) !important;
}

/* DEV-05 sub-MOQ inline warn state (Task 2 JS toggles this class on
   .merch-moq-hint at qty < data-min-tirazh). Text color measured 8.6:1 on
   the summary-inner background (#f8f8f5) — the raw --dof-warn token
   (#e67e22) alone only reaches ~2.68:1 there (fails AA), so the token is
   kept as an accent border only and the TEXT reuses the darker shade
   already proven for this exact MOQ-warning use case elsewhere in
   dof.css (.dh-mini-moq--warn: color:#6b3d00). */
.merch-moq-hint--warn {
	border-left: 2px solid var(--dof-warn, #e67e22);
	padding-left: 8px;
	color: #6b3d00;
	font-weight: 600;
}

/* Product technologies: make the native disclosure control unmistakably interactive. */
body.single-product .merch-tech-selector {
	margin: 22px 0;
}
body.single-product .merch-tech {
	border: 1px solid var(--wd-form-brd-color, #e8d9ab);
	background: var(--wd-main-bgcolor, #faeec6);
}
body.single-product .merch-tech + .merch-tech {
	border-top: 0;
}
body.single-product .merch-tech > summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	min-height: 48px;
	padding: 12px 42px 12px 14px;
	position: relative;
	cursor: pointer;
	font-weight: 600;
	list-style: none;
}
body.single-product .merch-tech > summary::-webkit-details-marker {
	display: none;
}
body.single-product .merch-tech > summary::after {
	content: "";
	position: absolute;
	right: 16px;
	width: 8px;
	height: 8px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg);
	transition: transform .2s ease;
}
body.single-product .merch-tech[open] > summary::after {
	transform: rotate(225deg);
}
body.single-product .merch-tech > summary:focus-visible {
	outline: 2px solid var(--wd-primary-color, #12263b);
	outline-offset: -2px;
}
body.single-product .merch-tech-desc {
	margin: 0;
	padding: 0 14px 14px;
}

/* Ph14 DEV-13 — mobile drawer body scroll-lock. Woodmart's mobile-nav (class-burger.php /
   mobileNavigation.js) has NO native scroll-lock: opening the drawer toggles a `.wd-opened`
   class only; the theme itself separately sets html's overflow-y to "hidden" via its own CSS
   at that point, which blocks real touch/wheel scrolling (user-input scroll IS already
   prevented natively) but — live-verified this session via CloakBrowser — Chromium still
   permits a PROGRAMMATIC window.scrollTo() to move the root scroller even while its overflow
   is hidden/clip. Only removing the root from normal flow (position:fixed) blocks scrollTo()
   outright; overflow:hidden/clip alone measured insufficient (both tested live, scrollY still
   reached the requested offset). This plan owns only merchlab-studio.css/qa-phase14.js (no new
   JS/PHP file) — the CSS-only fix below is a real, unavoidable trade-off: since there is no
   script to capture/restore the pre-open scrollY, the background visually resets to the top
   while position:fixed is in effect (same limitation any pure-CSS scroll-lock has without a
   companion script). A future plan can add a small JS top-offset compensation if the reset
   proves disruptive in practice; the underlying lock itself is genuine, not a check-only stub. */
html:has(.mobile-nav.wd-opened) {
	position: fixed !important;
	overflow: hidden !important;
	width: 100% !important;
	height: 100% !important;
}

/* Ph14 DEV-13 — drawer CTA + utility footer (merged mob-meniu content, 14-08 Task 1). CSS
   classes assigned via the WP menu item "CSS Classes" field (merch-drawer-cta / merch-drawer-
   phone) on the last two items — live-verified WP core's Walker_Nav_Menu (Woodmart's
   Mega_Menu_Walker included) always applies the menu item's `classes` field to the <li>
   wrapper, never the inner <a>, so `.ml-button`/`.ml-button--yellow` sit on the <li> (that is
   also what qa-phase14.js's dev13 CTA-visible check matches against — the existing sitewide
   button-class convention, no new selector needed there). The <li>'s own box is reset to
   neutral below so it doesn't double-box against the real button look, which is applied to the
   child <a> instead, consuming the --ml-btn-* token contract (14-03) per this plan's binding
   interface note. merch-drawer-phone is a plain utility row (native <a>, no button look). */
.mobile-nav li.merch-drawer-cta.ml-button {
	display: block;
	min-height: 0;
	padding: 0;
	border: 0;
	background: none;
}
.mobile-nav li.merch-drawer-cta > a.woodmart-nav-link {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px; /* one-off: icon-text gap, between --dof-sp-2(8) and --dof-sp-3(12) -- no exact rung, kept at its original measured value */
	width: calc(100% - (var(--dof-sp-4, 16px) * 2));
	margin: var(--dof-sp-4, 16px) var(--dof-sp-4, 16px) var(--dof-sp-2, 8px);
	min-height: var(--ml-btn-h-sm, 44px);
	padding: var(--ml-btn-pad-sm, 10px 16px);
	border-radius: var(--ml-btn-radius, 2px);
	background: var(--wd-alternative-color, #ffe786);
	color: var(--wd-title-color, #12263b);
	font-size: var(--ml-btn-fs, 11px);
	font-weight: var(--ml-btn-fw, 600);
	letter-spacing: var(--ml-btn-ls, .14em);
	text-transform: uppercase;
}
.mobile-nav li.merch-drawer-cta > a.woodmart-nav-link:hover,
.mobile-nav li.merch-drawer-cta > a.woodmart-nav-link:focus-visible {
	background: var(--wd-title-color, #12263b);
	color: var(--dof-on-dark);
}
.mobile-nav li.merch-drawer-phone > a.woodmart-nav-link {
	display: flex;
	align-items: center;
	margin: 0 var(--dof-sp-4, 16px) var(--dof-sp-3, 12px);
	padding: var(--dof-sp-2, 8px) 0;
	color: var(--dof-ink-2, color-mix(in srgb, var(--dof-ink) 72%, transparent));
	font-weight: 600;
}

/* ══════════════════════════════════════════════════════════════════
   Ph14 DEV-04 (14-09) — catalog filter chip touch target + tech-attribute casing.
   dof.css owns the chip/pill VISUAL shape (~L9578-9595 general round pill,
   ~L9603-9617 Woodmart-swatch variant, ~L9880-9901 Технологія/Матеріал-scoped
   rectangular-label variant) at 36px height, below the 44px touch-target floor.
   This file loads after dof.css, so re-declaring height at the SAME selector
   text (same specificity) wins on source order alone -- no dof.css edit
   needed, per this plan's Task 2 file scope. Only height moves to the shared
   --ml-btn-h-sm token; width/shape/color are untouched. Casing: text-
   transform:uppercase scoped strictly to the Технологія (filter_tech=) chip
   anchor and the product specs-table pa_tech value cell -- the two DB-backed
   attribute-term display surfaces RESEARCH identified (DTF/UV-DTF render
   lowercase because the term string itself is lowercase; the terms/slugs
   that feed URLs are NOT renamed, only their rendered casing). filter_
   material= chips are intentionally excluded (material names are ordinary
   prose, e.g. "Бавовна + поліестер", not an acronym dictionary).
   ══════════════════════════════════════════════════════════════════ */
.wd-widget .wd-swatches-filter > li.wc-layered-nav-term:not(.wd-swatch-wrap) .wd-filter-lable,
.wd-widget .wd-swatches-filter > li.wc-layered-nav-term:not(.wd-swatch-wrap) .layered-nav-link > span:not(.count),
.wd-widget .wd-swatches-filter .wd-swatch.wd-text {
	height: var(--ml-btn-h-sm, 44px) !important;
}
.wd-widget .wd-swatches-filter > li.wc-layered-nav-term > a.layered-nav-link[href*="filter_tech="] .wd-filter-lable,
.wd-widget .wd-swatches-filter > li.wc-layered-nav-term > a.layered-nav-link[href*="filter_material="] .wd-filter-lable {
	min-height: var(--ml-btn-h-sm, 44px) !important;
}
.wd-widget .wd-swatches-filter > li.wc-layered-nav-term > a.layered-nav-link[href*="filter_tech="] {
	text-transform: uppercase;
}
.woocommerce-product-attributes-item--attribute_pa_tech td,
.woocommerce-product-attributes-item--attribute_pa_tech .woocommerce-product-attributes-item__value {
	text-transform: uppercase;
}

/* ══════════════════════════════════════════════════════════════════
   R2-04 -- cart/checkout shipping-method radio vertically centered
   with its label (owner clarification 2026-08-12, KOSHYK-2 part 1).

   ROOT CAUSE (MEASURED live 2026-08-13, getBoundingClientRect() on
   /cart/, 1265px desktop viewport, product in cart, address defaulted
   to Kyiv oblast): radio center-Y vs label center-Y delta = -11.5px on
   BOTH shipping methods, identically on /cart/ and /checkout/. dof.css
   F-38/F-42/F-43 set `align-items: flex-start !important` on
   `.woocommerce-shipping-methods li` (cart + checkout, desktop +
   mobile — 3 identical declaration sites), which top-aligns the 13px
   radio against the li's cross axis. The label is a SEPARATE flex
   child sized by its own `.woocommerce label[for^="shipping_method_"]`
   rule (dof.css line ~359: `display:inline-flex; min-height:44px;
   align-items:center`) which vertically centers the label's own text
   INSIDE that 44px box. Top-aligning a 13px item next to a box whose
   content is centered in a taller box is exactly what produces the
   measured -11.5px mismatch.

   FIX PART 1: flip align-items to `center` on the same li selectors
   dof.css uses (identical specificity — this file is enqueued with a
   dep on `dof-main` in dof-init.php, so it loads after dof.css and
   wins the cascade on source order alone; no dof.css edit, matching
   this project's scope fence and the precedent noted above this
   block). One un-media-gated rule here beats dof.css's 3 separate
   desktop + mobile declarations, since cascade order is evaluated per
   matching rule regardless of which stylesheet carries a @media
   wrapper. This alone took the measured delta from -11.5px to a
   residual +4.0px (MEASURED live 2026-08-13, same method).

   FIX PART 2 (the residual +4px): traced to a SECOND, independent
   cause -- the Woodmart PARENT theme's own
   `wp-content/themes/woodmart/css/parts/woo-page-cart.min.css`
   ships `.woocommerce-shipping-methods input.shipping_method {
   position: relative; top: 4px; float: right; margin-inline: 7px 0; }`
   (MEASURED live 2026-08-13 via `document.styleSheets` rule
   enumeration + `Element.matches()` against the live radio). Our
   existing dof.css rules already neutralize the float/margin-inline
   part (confirmed computed `float: none`, `margin: 0 8px 0 0`), but
   nothing neutralized `position: relative; top: 4px`, which nudges
   the radio 4px down independently of flex alignment. Overriding
   `top` alone (even inline, even with `!important`) measurably had
   NO effect live -- `position: static !important` is what actually
   works: `position: static` makes `top` inert per spec regardless of
   any competing `top` declaration's specificity, so this doesn't
   depend on out-guessing Woodmart's own cascade. MEASURED live
   2026-08-13 (temporary injected stylesheet, same selectors as
   below): delta 4.0px -> 0.0px on both methods.
   ══════════════════════════════════════════════════════════════════ */
.woocommerce-checkout #order_review .woocommerce-shipping-methods li,
.woocommerce-cart .cart_totals .woocommerce-shipping-methods li {
	align-items: center !important;
}
.woocommerce-checkout #order_review .woocommerce-shipping-methods input[type="radio"],
.woocommerce-cart .cart_totals .woocommerce-shipping-methods input[type="radio"] {
	position: static !important;
}

/* ══════════════════════════════════════════════════════════════════
   Client UI audit remainder — DEV-06, DEV-12, DEV-14 (layout half),
   DEV-16, DEV-17 (2026-08-13). All five MEASURED live before this pass
   (merchlab.dofamini.com.ua, CloakBrowser/Claude_Browser + WP-CLI for
   product-attribute lookups); see each block's own comment for the
   specific reproduction.
   ══════════════════════════════════════════════════════════════════ */

/* DEV-06 -- catalogue card CTA colour semantics. MEASURED live (catalog page, 1280px,
   .merch-card-ctas children): "Додати на прорахунок" (.add_to_cart_button, dof.css ~L4153,
   4-class specificity) rendered BLACK (rgb(17,17,17)) while "В конструктор"
   (.dof-btn-secondary.merch-cta-constructor, dof.css ~L389, legacy pre-Ph14 class whose name
   predates the current yellow=primary/black=secondary convention) rendered YELLOW
   (rgb(243,227,25)) on every card that has a constructor CTA -- an exact inversion of the
   primary/secondary colour rule already followed on the product page and box page (both:
   yellow add-to-cart, ink-outline secondary). .dof-btn-secondary itself is left untouched
   (only .merch-cta-constructor is scoped here) since content-product.php is its only usage
   site-wide (grep-verified) -- no risk to any other surface. */
body.woocommerce.archive .wd-product .add_to_cart_button,
body.woocommerce.archive .wd-product .product_type_simple,
body.woocommerce.archive .wd-product .product_type_variable {
	background: var(--dof-accent, #ffe786) !important;
	border-color: var(--dof-accent, #ffe786) !important;
	color: var(--dof-ink, #12263b) !important;
}
/* Владелец 15.08 (п.2): --dof-accent-dk на живом резолвится в
   var(--btn-accented-bgcolor-hover) ≈ #151511 (dof.css:26) — ховер давал
   чёрный фон при чёрном тексте (--dof-ink). MEASURED через CDP
   getMatchedStylesForNode: computed bg rgb(21,21,17), color rgb(17,17,17).
   Инверсный ховер без битой переменной, в тон остальным кнопкам сайта.
   (Правила .merch-cta-constructor удалены — п.3, кнопки больше нет.) */
body.woocommerce.archive .wd-product .add_to_cart_button:hover,
body.woocommerce.archive .wd-product .product_type_simple:hover,
body.woocommerce.archive .wd-product .product_type_variable:hover {
	background: var(--dof-ink, #12263b) !important;
	border-color: var(--dof-ink, #12263b) !important;
	color: var(--dof-on-dark) !important;
}

/* DEV-16 -- product-page colour swatches + "Розмір" variation select onto the site's control
   scale. MEASURED live: .wd-swatch (Футболка Classic 180 г/м²) 35x35px; select#pa_size (a
   Neutraltex product, the only SKUs carrying a pa_size attribute) height 42px. Swatches go to
   --ml-btn-h-sm (44px, the sitewide touch-target floor -- not the full 48px, which would look
   oversized as a square selector); the select goes to the full --ml-btn-h (48px) per the
   brief's own explicit "site standard of 48". Both are Woodmart parent-theme defaults with no
   prior local override anywhere in this codebase (grep-verified), so no competing specificity
   to beat. */
.wd-swatches-product .wd-swatch {
	width: var(--ml-btn-h-sm, 44px) !important;
	height: var(--ml-btn-h-sm, 44px) !important;
}
.variations select,
.variations td select {
	height: var(--ml-btn-h, 48px) !important;
	min-height: var(--ml-btn-h, 48px) !important;
	padding-block: 0 !important;
	border-radius: var(--ml-btn-radius, 2px) !important;
}

/* DEV-16 -- cart coupon-toggle trigger onto the sitewide 44px touch-target floor. MEASURED
   live (/cart/): the native <summary>Є промокод?</summary> (cart.php) rendered at 20px tall,
   0 padding -- no rule anywhere styled it before this. */
.merch-coupon-toggle > summary {
	display: inline-flex;
	align-items: center;
	min-height: var(--ml-btn-h-sm, 44px);
	cursor: pointer;
}

/* DEV-17 -- catalogue/product-category archive H1 (.merch-catalog-title, rendered by
   merch-catalog-filters.php) had NO font-size rule anywhere in this codebase -- MEASURED live
   at 1280px it fell through to Woodmart's own bare h1-h6 default (dof.css ~L121 sets colour/
   weight/line-height but never font-size), landing at 28px, the smallest of six distinct H1
   sizes this audit found across the site (about/technologies 67.55px, home-hero 72px,
   contacts/cases 97.27px, request 81.06px [see .merch-request__intro h1 above], product-page
   35.13px, catalog 28px). Pulled onto the existing .ml-title section-heading token -- the
   closest analog, since catalog/merch-boxes/about/technologies are all interior content pages,
   not full-bleed heroes. Home/contacts/cases's .ml-display hero tier and the product page's own
   in-context .product_title scale are deliberate, already-token-driven tiers and are left as
   they are -- collapsing the hero/section/product-context distinction into one literal size
   sitewide would be a visual-hierarchy redesign this item didn't ask for and wasn't attempted. */
.merch-catalog-title {
	max-width: 18ch;
	margin: 0;
	font: 600 clamp(38px, 5vw, 76px)/.96 var(--wd-title-font);
	letter-spacing: -.055em;
	text-wrap: balance;
}

/* DEV-17 (closeout pass) -- cart/checkout/account H1. MEASURED live at 1280px BEFORE this
   rule: .merchlab-utility-title (dof.css ~L10279, Phase 10 "Woo shortcodes omit a visible
   H1" filler) computed font-size 50.6px at font-weight 500 -- a FIFTH size/weight pair the
   client's designer never asked for, on top of the four already-token-driven tiers above
   (.ml-display hero 91px, .ml-title/.merch-catalog-title section 63px, .product_title
   product-context 33px, plus home's OWN deliberate 72px hero override, Ph14 DEV-02, kept --
   see the comment above .ml-home-hero__copy .ml-display). Cart/checkout/account are interior
   utility pages, not heroes and not the product template -- the SAME bucket about/technologies
   already sit in -- so this reuses the identical .ml-title clamp formula/weight verbatim rather
   than inventing a fourth number, closing the client's "6 sizes, 3 weights" complaint down to
   the 3 tiers + 1 named exception DEV-17 itself asked for (page-title / section / product).
   Scoped to >=768px only: dof.css's OWN <768px media query (~L10289) already hand-tunes this
   class to a deliberate 32px mobile floor -- untouched, this rule never fires under it. Wins on
   source order at >=768px (identical .merchlab-utility-title specificity, this file is enqueued
   with a dep on dof-main/dof-init.php so it loads after dof.css -- the same mechanic the
   checkout-input override two blocks below already relies on). */
@media (min-width: 768px) {
	.merchlab-utility-title {
		font: 600 clamp(38px, 5vw, 76px)/.96 var(--wd-title-font);
		letter-spacing: -.055em;
	}
}

/* DEV-17 -- text-input/select control geometry unification. MEASURED live: four different
   input families with four different heights/radii in production -- lead-form fields
   (.merch-form/.dh-finp: 44px, 6px radius, #f4f4f5 tinted bg), checkout's .input-text (48px,
   0 radius, white bg, dof.css ~L3754), MyAccount fields (44px min-height only, dof.css ~L10112,
   otherwise bare Woodmart-core radius/bg with no local override at all) and the cart coupon
   field (dof.css ~L3633: 10px 12px padding, 0 radius, no min-height -- natural height under the
   44px floor). Converged onto the shared --ml-btn-h-sm (44px, the floor already used by
   .quantity/.dh-finp/MyAccount) and --ml-btn-radius (2px, the sitewide form-control radius
   token documented in the TOKEN-MAP CONTRACT above) -- geometry only. Each family's own
   background/border colour is deliberately left untouched (checkout's white-bg + WCAG-tuned
   border contrast work a few blocks above this one is a real, already-verified fix; a tinted
   lead-form-style bg on checkout was not asked for and risks that work). The checkout selector
   list is copy-pasted verbatim from dof.css's own rule (~L3754-3760) so this redeclaration has
   IDENTICAL specificity and wins purely on source order (this file is enqueued with a dep on
   dof-main, dof-init.php -- confirmed loads after dof.css), the same mechanic already used
   elsewhere in this file (see the DEV-14 cascade note above). */
.woocommerce-checkout .form-row input[type="text"],
.woocommerce-checkout .form-row input[type="tel"],
.woocommerce-checkout .form-row input[type="email"],
.woocommerce-checkout .form-row input[type="password"],
.woocommerce-checkout .form-row select,
.woocommerce-checkout .form-row textarea,
.woocommerce-checkout .select2-container--default .select2-selection--single {
	min-height: var(--ml-btn-h-sm, 44px) !important;
	border-radius: var(--ml-btn-radius, 2px) !important;
}
/* DEV-17 (closeout pass) -- lost-password was the one MyAccount surface the original DEV-17
   pass above missed: MEASURED live at 1280px, /account/lost-password/ (form.woocommerce-
   ResetPassword.lost_reset_password, same bare .woocommerce-Input.input-text markup as the
   login form) rendered at 48px -- WoodMart's unstyled default -- against every OTHER MyAccount
   field's 44px (this rule already forced their RADIUS but never their height, so login/register/
   edit-account already sat at the .quantity/.dh-finp 44px floor by coincidence of a DIFFERENT
   theme default, not by this rule). Added to the same selector list, plus the min-height this
   block was missing for the whole family -- closes the last of the four families named in the
   client's brief onto the shared 44px/2px token. */
.woocommerce-account .woocommerce-MyAccount-content input,
.woocommerce-account .woocommerce-MyAccount-content select,
.woocommerce-account .woocommerce-MyAccount-content textarea,
.woocommerce-account .woocommerce-form-login input,
.woocommerce-account .woocommerce-form-register input,
.woocommerce-account .woocommerce-ResetPassword input {
	min-height: var(--ml-btn-h-sm, 44px) !important;
	border-radius: var(--ml-btn-radius, 2px) !important;
}
.woocommerce-cart .coupon input[name="coupon_code"] {
	min-height: var(--ml-btn-h-sm, 44px) !important;
	border-radius: var(--ml-btn-radius, 2px) !important;
	box-sizing: border-box;
}
.woocommerce-cart .coupon button[name="apply_coupon"] {
	min-height: var(--ml-btn-h-sm, 44px) !important;
	border-radius: var(--ml-btn-radius, 2px) !important;
	box-sizing: border-box;
}

/* ══════════════════════════════════════════════════════════════════
   DEV-12 / DEV-14 (layout half) -- 768-1023px tablet band gets the SAME
   product-page bottom-toolbar clearance and sticky-CTA swap the phone
   band (<=767px) already has. Every one of dof.css's mobile rules for
   this (.wd-toolbar hide ~L6478-6515, .merch-sticky-cta show ~L6551-6567,
   #main-content padding-bottom reserve ~L10011-10021) is gated to
   max-width:767px, so at 768-1023 none of them fire.

   MEASURED live (768px viewport, product page, scrolled to y=700):
   .wd-toolbar stays visible (fixed, 55px, z-index:350) while
   #main-content keeps the unconditional 40px Phase-10 padding-bottom (no
   reserve for the bar). Separately, .product-images keeps its DESKTOP
   position:sticky (top:104px) even though .product-image-summary-wrap has
   ALREADY collapsed to one stacked column at this width (both children
   measured full-width, 723px, same as the parent) -- a sticky block
   sibling in normal (non-grid-column) flow overlaps the sibling that
   follows it as the page scrolls, because position:sticky only pins the
   element's own box, it does not reserve column space the way a true
   grid track would. Reproduced exactly: at scrollY 700, .product-images
   stayed pinned at top:104/bottom:1071 while .summary-inner's own top
   (position:static, normal flow) moved to 433 -- printing summary content
   inside the gallery's box, with the gallery (a positioned element)
   painting over it per CSS stacking-order rules. Fix mirrors the existing
   <=767px treatment exactly (same values, same selectors), scoped to this
   band only -- verified this does not touch <=767 or >=1024 behaviour. */
@media (min-width: 768px) and (max-width: 1023px) {
	body.single-product .product-images {
		position: relative !important;
		top: auto !important;
	}

	body.single-product .wd-toolbar {
		display: none !important;
	}

	body.single-product .scrollToTop {
		bottom: calc(69px + 12px + env(safe-area-inset-bottom)) !important;
	}

	body.single-product .merch-sticky-cta {
		display: flex;
	}

	body.single-product .merch-sticky-cta.is-shown {
		transform: translateY(0);
		opacity: 1;
		visibility: visible;
		transition: transform 220ms ease, opacity 220ms ease, visibility 0s linear 0s;
		pointer-events: auto;
	}

	body.single-product #main-content {
		padding-bottom: max(88px, calc(92px + env(safe-area-inset-bottom))) !important;
	}
}
@media (min-width: 768px) and (max-width: 1023px) and (prefers-reduced-motion: reduce) {
	body.single-product .merch-sticky-cta,
	body.single-product .merch-sticky-cta.is-shown {
		transition: visibility 0s linear;
	}
}

/* DEV-07 (acceptance sweep, 2026-08-13): the header cart total was invisible on
 * /cart/, /checkout/ and /account/ — exactly the pages where a buyer looks at
 * it, and exactly the page the client screenshotted (image9).
 * MEASURED by pixel-sampling the rendered `.wd-cart-subtotal`: on those pages
 * the box contains only rgb(10,10,10) (header ground) and rgb(17,17,17)
 * (glyphs) — contrast 1.05:1; on every other page the same element measures
 * 19.46:1. Cause is ours: dof.css paints
 * `.woocommerce-cart .woocommerce-Price-amount { color: var(--dof-ink) }` for
 * page content, and the selector reaches inside the dark header too. Put the
 * header back to white — scoped to the header only, so page prices keep the
 * ink colour that rule is actually for. */
.woocommerce-cart .whb-header .woocommerce-Price-amount,
.woocommerce-checkout .whb-header .woocommerce-Price-amount,
.woocommerce-account .whb-header .woocommerce-Price-amount,
.woocommerce-cart .whb-header .wd-cart-subtotal .amount,
.woocommerce-checkout .whb-header .wd-cart-subtotal .amount,
.woocommerce-account .whb-header .wd-cart-subtotal .amount,
.woocommerce-cart .whb-header .wd-tools-element .woocommerce-Price-currencySymbol,
.woocommerce-checkout .whb-header .wd-tools-element .woocommerce-Price-currencySymbol,
.woocommerce-account .whb-header .wd-tools-element .woocommerce-Price-currencySymbol {
	color: var(--dof-on-dark) !important;
}


/* ==========================================================================
   Приёмочные доработки 13.08 — план утверждён владельцем.
   Каждый блок помечен номером пункта клиентского ТЗ.
   ========================================================================== */

/* DEV-17: display-заголовки /cases/ и /contacts/ (h1.ml-display, 92px) — в
   общую шкалу 64px; мобильный размер не трогаем. */
@media (min-width: 768px) {
	h1.ml-display { font-size: 64px !important; }
}

/* DEV-03: названия карточек резались по нижней трети строки (контейнер 42.5px,
   overflow hidden). Честный двухстрочный кламп с многоточием. */
.product-grid-item .wd-entities-title {
	height: auto !important;
	min-height: 44px;
}
.product-grid-item .wd-entities-title a {
	display: -webkit-box !important;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* DEV-03/DEV-06: блок CTA прижат к низу карточки; «В конструктор» — компактная
   вторичная ссылка ПОД жёлтой кнопкой. Дыра на карточках без конструктора
   сжимается до одной 26px-строки, жёлтая кнопка везде на одном уровне. */
.product-grid-item .product-element-bottom {
	display: flex;
	flex-direction: column;
	height: 100%;
}
.product-grid-item .merch-card-ctas {
	margin-top: auto;
	display: flex;
	flex-direction: column;
	gap: 8px;
}
/* (перекраску «В конструктор» откатили — кнопка на каждой карточке в исходном вторичном стиле) */

/* DEV-10: верх checkout — 309px до первого поля. Заголовок и строки
   входа/промокода компактнее. */
.woocommerce-checkout h1 {
	font-size: 44px !important;
	margin-bottom: 14px !important;
}
.woocommerce-checkout .woocommerce-form-login-toggle .woocommerce-info,
.woocommerce-checkout .woocommerce-form-coupon-toggle .woocommerce-info {
	background: none !important;
	border: 0 !important;
	padding: 4px 0 !important;
	margin: 0 0 4px !important;
}

/* DEV-11: границы полей checkout были 1.12:1 к фону. rgba(17,17,17,.45) по
   белому даёт ~3.2:1 — видно, и не спорит с фокус-стилями (они на box-shadow). */
.woocommerce-checkout input.input-text,
.woocommerce-checkout select,
.woocommerce-checkout textarea {
	border: 1px solid color-mix(in srgb, var(--dof-ink) 45%, transparent) !important;
}

/* DEV-16: «Є промокод?» был 20px-текстом. Нормальная зона нажатия и явный вид
   ссылки. */
.woocommerce-form-coupon-toggle .showcoupon {
	display: inline-flex !important;
	align-items: center !important;
	min-height: 44px !important;
	padding: 0 4px !important;
	font-size: 14px !important;
	font-weight: 600 !important;
	color: var(--dof-ink) !important;
	text-decoration: underline !important;
	text-underline-offset: 3px !important;
}

/* DEV-12: липкая панель (69px) перекрывала низ страницы — резерв под неё. */
body:has(.merch-sticky-cta) {
	padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px)) !important;
}

/* DEV-15 (телефон): «Додати коментар до замовлення» стоял НИЖЕ кнопки
   отправки. Поднимаем блок в начало правой колонки. */
@media (max-width: 767.98px) {
	.checkout-order-review {
		display: flex;
		flex-direction: column;
	}
	.checkout-order-review > .merch-notes-toggle {
		order: -1;
		margin: 0 0 14px;
	}
}

/* TAIL-9: адрес в подвале вылезал за колонку (nowrap в 200px). */
[class*="dof-footer"] p,
[class*="dof-footer"] li,
[class*="dof-footer"] address {
	white-space: normal !important;
}

/* Решение владельца 13.08: радиокнопки — чёрные, в стиле сайта (были
   фиолетовые браузерные). */
input[type="radio"],
input[type="checkbox"] {
	accent-color: var(--dof-ink) !important;
}

/* Решение владельца 13.08: «Не вказано» не выводить как выбираемый цвет. */
.wd-swatch[data-value="ne-vkazano"] {
	display: none !important;
}

/* КОШИК-7, решение владельца 13.08: промокод доступен и в корзине на
   телефоне — тема прятала весь ряд действий (tr.wd-cart-action-row). */
@media (max-width: 768.98px) {
	/* selector matches the theme's own hiding rule specificity-for-specificity */
	.woocommerce-cart table.shop_table tbody tr.wd-cart-action-row,
	.woocommerce-cart table.shop_table_responsive tr.wd-cart-action-row,
	.woocommerce-cart tr.wd-cart-action-row {
		display: flex !important;
		width: 100%;
	}
	.woocommerce-cart tr.wd-cart-action-row td.actions {
		display: flex;
		flex-direction: column;
		gap: 12px;
		width: 100%;
		padding: 14px 0;
	}
}


/* DEV-16 + КОШИК-7 + DEV-15, правка владельца 13.08 (вторая итерация):
   «Є промокод?» (checkout и корзина) и «Додати коментар до замовлення» —
   видимые ВТОРИЧНЫЕ кнопки в стиле сайта (белая, рамка, без акцента). */
.woocommerce-form-coupon-toggle .showcoupon,
.merch-coupon-toggle > summary,
.merch-notes-toggle > summary {
	display: inline-flex !important;
	align-items: center !important;
	justify-content: center !important;
	gap: 8px !important;
	min-height: 44px !important;
	padding: 0 18px !important;
	border: 1px solid var(--dof-line-strong) !important;
	border-radius: 4px !important;
	background: var(--dof-bg-2) !important;
	color: var(--dof-ink) !important;
	font-size: 12px !important;
	font-weight: 700 !important;
	letter-spacing: .1em !important;
	text-transform: uppercase !important;
	text-decoration: none !important;
	cursor: pointer !important;
	list-style: none !important;
	width: fit-content !important;
	transition: border-color .15s ease !important;
}
.woocommerce-form-coupon-toggle .showcoupon:hover,
.merch-coupon-toggle > summary:hover,
.merch-notes-toggle > summary:hover {
	border-color: var(--dof-ink) !important;
}
.merch-coupon-toggle > summary::-webkit-details-marker,
.merch-notes-toggle > summary::-webkit-details-marker {
	display: none !important;
}
.merch-coupon-toggle > summary::after,
.merch-notes-toggle > summary::after {
	content: "+";
	font-size: 15px;
	line-height: 1;
}
.merch-coupon-toggle[open] > summary::after,
.merch-notes-toggle[open] > summary::after {
	content: "−";
}
.merch-notes-toggle textarea {
	width: 100% !important;
	min-height: 110px !important;
	margin-top: 12px !important;
	border: 1px solid color-mix(in srgb, var(--dof-ink) 45%, transparent) !important;
	border-radius: 4px !important;
	padding: 12px 14px !important;
}


/* Правки владельца 13.08, вторая итерация ревью. */

/* 1) «В конструктор» — в одну строку. */
.product-grid-item .merch-card-ctas .merch-cta-constructor {
	white-space: nowrap !important;
}

/* 2) Кнопки-раскрывашки: выравнивание и воздух. */
/* checkout: «Є промокод?» + кнопка — одна строка, по базовой линии контента,
   с нормальными отступами сверху/снизу */
.woocommerce-checkout .woocommerce-form-coupon-toggle .woocommerce-info {
	display: flex !important;
	align-items: center !important;
	gap: 14px !important;
	padding: 0 !important;
	margin: 14px 0 26px !important;
}
.woocommerce-checkout .woocommerce-form-login-toggle .woocommerce-info {
	margin: 0 0 10px !important;
}
/* комментарий к заказу: не липнуть к полю выше и заголовку ниже */
.merch-notes-toggle {
	display: block !important;
	margin: 22px 0 16px !important;
}
.merch-notes-toggle[open] {
	margin-bottom: 22px !important;
}
/* корзина: кнопка промокода по левому краю колонки, не по центру */
.woocommerce-cart .cart-actions {
	align-items: flex-start !important;
}
.merch-coupon-toggle {
	margin: 16px 0 !important;
}
.merch-coupon-toggle > summary {
	margin: 0 !important;
}
@media (max-width: 768.98px) {
	.woocommerce-cart tr.wd-cart-action-row td.actions {
		align-items: flex-start !important;
	}
}

/* раскрытый комментарий: воздух между кнопкой и заголовком блока */
.merch-notes-toggle[open] > summary {
	margin-bottom: 16px !important;
}


/* Владелец, 13.08 — конструкторский товар в корзине/чекауте. */

/* «Колір» плашкой: у вендорных чипов инлайновый фон — глушим и на случай,
   если разметка придёт до PHP-очистки (кэш фрагментов). */
.cart_item dl.variation dd span[style],
.cart_item .wc-item-meta span[style],
.woocommerce-checkout-review-order-table .cart_item span[style]:not(.woocommerce-Price-amount) {
	background: transparent !important;
	color: var(--dof-ink) !important;
	padding: 0 !important;
	border-radius: 0 !important;
}

/* Чекаут, блок «Ваше замовлення»: мини-мокап, название, «× 10» и цена — в
   одну аккуратную сетку вместо разъехавшихся строк. */
.woocommerce-checkout-review-order-table td.product-name {
	display: grid !important;
	grid-template-columns: 56px 1fr !important;
	column-gap: 12px !important;
	align-items: start !important;
}
.woocommerce-checkout-review-order-table td.product-name > img,
.woocommerce-checkout-review-order-table td.product-name .merchlab-checkout-thumb {
	grid-column: 1 !important;
	grid-row: 1 / span 3 !important;
	width: 56px !important;
	height: auto !important;
	margin: 0 !important;
}
.woocommerce-checkout-review-order-table td.product-name .product-quantity {
	display: inline !important;
	float: none !important;
	margin-left: 6px !important;
	font-weight: 600 !important;
}
.woocommerce-checkout-review-order-table td.product-name dl.variation {
	grid-column: 2 !important;
	margin: 6px 0 0 !important;
}
.woocommerce-checkout-review-order-table td.product-name dl.variation dt,
.woocommerce-checkout-review-order-table td.product-name dl.variation dd {
	display: inline-block !important;
	margin: 0 6px 2px 0 !important;
	padding: 0 !important;
	float: none !important;
}
.woocommerce-checkout-review-order-table td.product-total {
	vertical-align: top !important;
	padding-top: 14px !important;
	white-space: nowrap !important;
	text-align: right !important;
}
.woocommerce-checkout-review-order-table .merchlab-edit-design {
	display: inline-flex !important;
	min-height: 32px !important;
	padding: 4px 12px !important;
	font-size: 11px !important;
}

/* «Додати коментар»: внутри раскрытого блока убрать служебный заголовок
   «Додаткова інформація» и подпись «Нотатки до замовлень» — сразу поле. */
.merch-notes-toggle h2,
.merch-notes-toggle h3,
.merch-notes-toggle .woocommerce-additional-fields > h3,
.merch-notes-toggle label {
	display: none !important;
}
.merch-notes-toggle .form-row,
.merch-notes-toggle p {
	margin: 0 !important;
	padding: 0 !important;
}
.merch-notes-toggle .woocommerce-additional-fields {
	border: 0 !important;
}

/* ══════════════════════════════════════════════════════════════════
   Ревью владельца 15.08 — точечные правки (пп. 5, 7, 8)
   ══════════════════════════════════════════════════════════════════ */

/* п.5: sticky footer. На коротких страницах (кабинет «Документи»/«Профіль»)
   документ ниже вьюпорта не дотягивал, и светлый фон .wd-page-wrapper
   просвечивал ПОД тёмным футером (#0a0a0a). Механизма прижатия футера в теме
   не было вовсе (grep min-height по всем css — ноль попаданий по обёрткам). */
.wd-page-wrapper {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	min-height: 100svh;
}
.wd-page-wrapper .main-page-wrapper {
	flex: 1 0 auto;
}

/* п.7: «Отримати рекомендацію» в жёлтой секции .ml-brief — глобальный ховер
   .ml-button красит фон в --wd-alternative-color, и на жёлтом префутере кнопка
   сливалась с фоном. Внутри жёлтой секции ховер остаётся чёрным (сдвиг
   translateY наследуется от базового правила). */
.ml-brief .ml-button:hover {
	border-color: var(--wd-title-color);
	background: var(--wd-title-color);
	color: var(--dof-on-dark);
}

/* п.8: счётчик буллета фильтра. На ховере WoodMart красит .count в
   var(--wd-primary-color) (тёмный овал, правило a:hover + .count), а dof.css
   держит цифру #888 !important — серое на чёрном, не прочесть. Белая цифра
   на чёрном овале, в тон самой плашке. */
.wd-filter-list .wc-layered-nav-term a:hover ~ .count,
.wd-filter-list .wc-layered-nav-term.wd-active .count,
.wd-widget .wd-swatches-filter > li a:hover ~ .count,
.wd-widget .wd-swatches-filter > li.chosen .count {
	color: var(--dof-on-dark) !important;
	background-color: var(--dof-ink, #12263b) !important;
	border-color: var(--dof-ink, #12263b) !important;
}

/* ══════════════════════════════════════════════════════════════════
   Visual Style Update 2026-09-15 (quick 260915-mtx) — post-recolour
   contrast fixes, each MEASURED live after the token swap.
   ══════════════════════════════════════════════════════════════════ */

/* Kickers inside dark heroes inherited the dark-pink link-hover token
   (2.6:1 on navy). On dark surfaces the eyebrow is the yellow accent. */
.ml-page-hero .ml-kicker,
.merch-case-hero .ml-kicker,
.ml-site .ml-page-hero .ml-kicker {
	color: var(--dof-accent);
}

/* Accent used as TEXT on the cream base: cart manager card, required
   asterisks — raw yellow is ~1.1:1 there; use the darkened pink text token. */
.dh-cart-manager__tg {
	color: var(--dof-accent-2-text) !important;
}
.dh-cart-manager__avatar {
	background: var(--dof-surface-dark) !important;
	color: var(--dof-accent) !important;
}
.woocommerce form .form-row .required,
.merch-form .required,
span.required {
	color: var(--dof-accent-2-text);
}

/* WoodMart muted greys that never went through the token layer. */
.wd-products-per-page,
.wd-products-per-page a,
.wd-side-hidden .quantity {
	color: var(--dof-ink-3);
}

/* WoodMart off-canvas panels and the mobile toolbar stayed white. */
.wd-side-hidden,
.wd-toolbar {
	background-color: var(--dof-bg-2) !important;
}

/* ══════════════════════════════════════════════════════════════════
   Visual Style Update — ROUND 2 (client review 2026-09-17, quick 260917):
   sheet «02 Блоки» block map + Google-doc remarks + sheet «01» typography.
   This block intentionally comes last and overrides the round-1 recolour.
   ══════════════════════════════════════════════════════════════════ */

/* ---- Typography roles (sheet 01 §3) ---- */
h1, .ml-display {
	font-family: var(--ml-font-sans);
	font-weight: 800;
	font-size: var(--dof-fs-h1);
	line-height: .94;
	letter-spacing: -.035em;
}
h2, .ml-title, .ml-section-head h2, .woocommerce-products-header__title {
	font-family: var(--ml-font-display);
	font-weight: 600;
	font-size: var(--dof-fs-h2);
	line-height: 1.05;
	letter-spacing: -.025em;
	text-transform: none;
}
h3, .ml-section h3, .product-title, .wd-entities-title, .ml-box-card__body h3, .merch-case-card h3 {
	font-family: var(--ml-font-sans);
	font-weight: 700;
	line-height: 1.18;
	letter-spacing: -.015em;
}
.ml-lead { font-size: var(--dof-fs-lead); line-height: 1.5; letter-spacing: 0; }
body, .ml-site p { line-height: 1.55; }
/* H1 accent: one short phrase, Cormorant Garamond 500 italic, rose-dark (3.87:1 on cream —
   large text only, which an H1 always is). */
.ml-h1-accent, h1 .ml-h1-accent {
	font-family: var(--ml-font-accent);
	font-style: italic;
	font-weight: 500;
	letter-spacing: -.015em;
	color: var(--ml-rose-dark);
}
.ml-home-hero__copy .ml-display .ml-h1-accent { font-size: 1.06em; }
/* Beats the round-1 `.ml-home-hero__copy .ml-display em` (yellow, font-style:normal). */
.ml-home-hero__copy .ml-display em.ml-h1-accent, h1 em.ml-h1-accent {
	color: var(--ml-rose-dark) !important;
	font-style: italic !important;
	font-family: var(--ml-font-accent) !important;
	font-weight: 500 !important;
}
/* Page-hero H1s carry .ml-title (H2-styled by the section rule above); the H1 role is Onest 800. */
h1.ml-title, h1.ml-display { font-family: var(--ml-font-sans); font-weight: 800; letter-spacing: -.035em; line-height: .94; }
/* Card / product CTAs: beat dof.css's 4-class add-to-cart rule for the font family. */
body.woocommerce.archive .wd-product .add_to_cart_button,
body.woocommerce.archive .wd-product .merch-card-ctas > *,
body.single-product .single_add_to_cart_button,
.woocommerce .button, .woocommerce button.button { font-family: var(--ml-font-sans) !important; }
/* Footer italic accent follows the same family. */
.dof-serif-italic { font-family: var(--ml-font-accent); font-weight: 500; }
/* KPI numbers: Bitter 600, value and unit never split. */
.ml-proofbar__value {
	font: 600 clamp(36px, 2rem + 1.4vw, 64px)/1 var(--ml-font-display) !important;
	letter-spacing: -.02em !important;
	white-space: nowrap;
}

/* ---- Buttons (G-04 + sheet 01): Onest 700 16px, no tracking, pill radius, ≥44px ---- */
:root {
	--ml-btn-radius: 999px;
	--ml-btn-fs: 16px;
	--ml-btn-ls: .01em;
	--ml-btn-fw: 700;
	--ml-btn-focus-ring: 0 0 0 2px var(--ml-cream), 0 0 0 5px var(--ml-yellow);
}
.ml-button, .button, .btn, .merch-form__submit, .single_add_to_cart_button, .add_to_cart_button,
.woocommerce button.button, .wc-block-components-button, .wd-btn, .merch-card-ctas > * {
	border-radius: 999px !important;
	font-family: var(--ml-font-sans) !important;
	font-weight: 700 !important;
	font-size: 16px !important;
	letter-spacing: .01em !important;
	text-transform: none !important;
	line-height: 1.2 !important;
	min-height: 44px;
}
/* Primary = navy/cream, hover deep navy. */
.ml-button, .merch-form__submit, .woocommerce #payment #place_order, .checkout-button, .wc-proceed-to-checkout .button {
	background: var(--ml-navy) !important;
	border-color: var(--ml-navy) !important;
	color: var(--ml-cream) !important;
	transform: none;
}
.ml-button:hover, .merch-form__submit:hover, .woocommerce #payment #place_order:hover, .checkout-button:hover, .wc-proceed-to-checkout .button:hover {
	background: var(--ml-navy-deep) !important;
	border-color: var(--ml-navy-deep) !important;
	color: var(--ml-cream) !important;
}
/* Mobile drawer CTA: the button classes sit on the <li> (WP walker), so the <li> stays a neutral box and the
   link itself gets the single primary navy pill (owner 2026-09-18: was a navy pill around a yellow one). */
.mobile-nav li.merch-drawer-cta.ml-button { background: none !important; border: 0 !important; padding: 0 !important; min-height: 0 !important; }
.mobile-nav li.merch-drawer-cta > a.woodmart-nav-link { background: var(--ml-navy); color: var(--ml-cream); text-transform: none; }
.mobile-nav li.merch-drawer-cta > a.woodmart-nav-link:hover, .mobile-nav li.merch-drawer-cta > a.woodmart-nav-link:focus-visible { background: var(--ml-navy-deep); color: var(--ml-cream); }
/* Navy sections (about-page prefooter): the aside text/rule were navy-on-navy and the primary navy button vanished. */
.ml-production .ml-statement__aside { border-left-color: rgba(219, 231, 251, .35); }
.ml-production .ml-statement__aside p { color: var(--ml-blue-light) !important; }
.ml-production .ml-button { background: var(--ml-yellow) !important; border-color: var(--ml-yellow) !important; color: var(--ml-navy-deep) !important; }
.ml-production .ml-button:hover { background: var(--ml-cream) !important; border-color: var(--ml-cream) !important; color: var(--ml-navy-deep) !important; }
/* Accent = yellow/navy (add-to-cart, badges) — kept from round 1, radius only. */
/* Secondary = transparent + navy border. */
.ml-button--light, .ml-button--outline, .dof-btn-secondary {
	background: transparent !important;
	border: 1.5px solid var(--ml-navy) !important;
	color: var(--ml-navy) !important;
}
.ml-button--light:hover, .ml-button--outline:hover, .dof-btn-secondary:hover {
	background: var(--ml-navy) !important;
	color: var(--ml-cream) !important;
}
.ml-button:focus-visible, .button:focus-visible, .merch-form__submit:focus-visible {
	box-shadow: var(--ml-btn-focus-ring) !important;
	outline: none !important;
}

/* ---- Header (G-01): powder menu, hover/active yellow, thin powder 20% bottom edge ---- */
body:not(.lumise-editor-page) .whb-general-header { border-bottom: 1px solid rgba(219, 231, 251, .2); }
body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li > a,
body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li > a .nav-link-text,
body:not(.lumise-editor-page) .whb-general-header .wd-header-my-account .wd-tools-text,
body:not(.lumise-editor-page) .whb-general-header .wd-header-cart .wd-tools-text,
body:not(.lumise-editor-page) .whb-general-header .wd-header-cart .wd-cart-subtotal {
	color: var(--ml-blue-light) !important;
	font-family: var(--ml-font-sans) !important;
	font-weight: 600 !important;
	letter-spacing: .04em !important;
}
/* Nav size: the TZ asks 14px desktop, but 7 items + phone + account + cart wrap to a second
   row below ~1600px (measured: navWrap=2 at 1440 with 14px). Stepped so the row never wraps. */
@media (min-width: 1700px) {
	body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li > a { font-size: 13px !important; }
}
@media (min-width: 1440px) and (max-width: 1699px) {
	body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li > a { font-size: 11.5px !important; letter-spacing: .03em !important; }
	body:not(.lumise-editor-page) .whb-general-header .wd-nav-main { gap: 0 9px !important; }
}
@media (min-width: 1025px) and (max-width: 1439px) {
	body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li > a { font-size: 10.5px !important; letter-spacing: .02em !important; }
	body:not(.lumise-editor-page) .whb-general-header .wd-nav-main { gap: 0 8px !important; }
	.whb-header .merchlab-logo .merchlab-logo__desktop { height: 34px; }
}
/* Nav items must never wrap inside themselves either. */
body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li > a { white-space: nowrap; }
body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li:hover > a,
body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li.current-menu-item > a,
body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li.wd-opened > a,
body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li > a:hover,
body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li > a:hover .nav-link-text,
body:not(.lumise-editor-page) .whb-general-header .wd-nav-main > li.current-menu-item > a .nav-link-text {
	color: var(--ml-yellow) !important;
}
/* Logo images (round 2 replaces the text wordmark everywhere). */
/* Owner 2026-09-17: desktop = horizontal icon+name lockup, mobile header = compact
   icon+stacked-name lockup. Both <img>s live in the header block; media queries pick one. */
.merchlab-logo { display: inline-flex; align-items: center; line-height: 0; }
.merchlab-logo img { height: 36px; width: auto; display: block; }
.merchlab-logo .merchlab-logo__mobile { display: none; }
.whb-sticky-header .merchlab-logo img, .whb-header-clone .merchlab-logo img { height: 32px; }
.dof-footer__brand .merchlab-logo img { height: 44px; }
@media (max-width: 1024px) {
	.whb-header .merchlab-logo .merchlab-logo__desktop { display: none; }
	.whb-header .merchlab-logo .merchlab-logo__mobile { display: block; height: 40px; }
}

/* ---- Footer (G-03): navy, cream/powder text, yellow link hover ---- */
.dof-footer__col a:hover, .dof-footer a:hover, .dof-footer__col a:focus-visible { color: var(--ml-yellow) !important; }
.dof-footer__col h3.dof-footer__col-h { color: var(--ml-blue-light); opacity: .85; }

/* ---- Forms (G-05): light-cream fields, navy 25% border, yellow focus ring ---- */
.merch-form input, .merch-form select, .merch-form textarea,
.woocommerce form .form-row input.input-text, .woocommerce form .form-row select, .woocommerce form .form-row textarea,
.wd-search-form input[type="text"], .woocommerce-cart-form .quantity input {
	background: var(--ml-cream-light) !important;
	border: 1px solid rgba(29, 68, 109, .25) !important;
	border-radius: 8px !important;
	color: var(--ml-navy-deep) !important;
}
.merch-form input:focus-visible, .merch-form select:focus-visible, .merch-form textarea:focus-visible,
.woocommerce form .form-row input.input-text:focus-visible, .woocommerce form .form-row select:focus-visible, .woocommerce form .form-row textarea:focus-visible {
	outline: none !important;
	border-color: var(--ml-navy) !important;
	box-shadow: 0 0 0 3px var(--ml-yellow) !important;
}
.merch-form label, .woocommerce form .form-row label { color: var(--ml-navy); }

/* ---- Cards (sheet 01: powder for cards, fields, media underlays) ---- */
.ml-moments__item,
.ml-box-card,
.merch-case-card,
body.woocommerce.archive .wd-product .wd-product-wrapper,
.wd-product.product-grid-item { background: var(--ml-blue-light) !important; border-color: rgba(29, 68, 109, .18) !important; }
.ml-box-card__media { background: var(--ml-blue-light) !important; }
/* Technologies rows: light cream per H-09. */
.ml-tech-row { background: var(--ml-cream-light) !important; }
/* Box card price / savings: price navy, savings rose-dark. */
.ml-box-card__body strong, .ml-box-card__price ins { color: var(--ml-navy) !important; }
.ml-box-card__body > span, .ml-box-card__save { color: var(--ml-rose-dark) !important; font-weight: 600; }

/* ---- H-01 Hero: cream background, navy copy, rose accent, blue buttons (doc ruling) ---- */
.ml-home-hero { background: var(--ml-cream) !important; color: var(--ml-navy-deep) !important; }
.ml-home-hero__copy { background: var(--ml-cream) !important; }
.ml-home-hero__copy .ml-display { color: var(--ml-navy-deep) !important; }
.ml-home-hero__copy .ml-lead { color: var(--ml-navy) !important; }
.ml-home-hero__copy .ml-kicker { color: var(--ml-navy) !important; }
.ml-home-hero__copy .ml-kicker::before { background: var(--ml-rose) !important; }
.ml-home-hero__actions .ml-button--yellow {
	background: var(--ml-navy) !important;
	border-color: var(--ml-navy) !important;
	color: var(--ml-cream) !important;
}
.ml-home-hero__actions .ml-button--yellow:hover { background: var(--ml-navy-deep) !important; border-color: var(--ml-navy-deep) !important; }
.ml-home-hero__actions .ml-button--light { background: transparent !important; border: 1.5px solid var(--ml-navy) !important; color: var(--ml-navy) !important; }
.ml-home-hero__actions .ml-button--light:hover { background: var(--ml-navy) !important; color: var(--ml-cream) !important; }
.ml-home-hero__note { background: var(--ml-navy) !important; color: var(--ml-cream) !important; }
.ml-home-hero__note strong { color: var(--ml-yellow) !important; }

/* ---- H-02 Культурний бриф: light cream, thin navy 15% lines ---- */
.ml-section.ml-cultural-brief { background: var(--ml-cream-light); }
.ml-cultural-brief table, .ml-cultural-brief tr, .ml-cultural-brief th, .ml-cultural-brief td { border-color: rgba(29, 68, 109, .15) !important; }
.ml-cultural-brief th, .ml-cultural-brief dt { color: var(--ml-navy-deep); }

/* ---- H-04 KPI: navy section, yellow numbers, powder labels ---- */
.ml-proofbar { background: var(--ml-navy) !important; border: 0 !important; }
.ml-proofbar__value { color: var(--ml-yellow) !important; }
.ml-proofbar__label { color: var(--ml-blue-light) !important; }
.ml-proofbar__item { border-color: rgba(219, 231, 251, .2) !important; }

/* ---- H-05 Мерч-система: cream, navy title, rose/yellow markers ---- */
.ml-checks li::before, .ml-checks li::marker { color: var(--ml-rose); background: var(--ml-rose); }
.ml-statement__aside p { color: var(--ml-text-secondary); }

/* ---- H-07 4 кроки: navy, powder/cream steps, yellow numbers, powder 30% borders ---- */
.ml-production { background: var(--ml-navy) !important; }
.ml-production .ml-title, .ml-production h3 { color: var(--ml-cream) !important; }
.ml-production .ml-process-step p { color: var(--ml-blue-light) !important; }
.ml-process-step { border-color: rgba(219, 231, 251, .3) !important; }
.ml-process-step__number { color: var(--ml-yellow) !important; }
/* ---- H-08 CTA конструктора: rose surface, deep-navy text, navy primary button ---- */
/* BNR-02 / BNR-02M (TZ sheet 03): photo under a deep-navy overlay (45–65%), HTML text on top — replaces the
   round-2 rose fill once the client delivered the files (2026-09-17). */
.ml-constructor-callout { position: relative; isolation: isolate; overflow: hidden; background: var(--ml-navy-deep) !important; color: var(--ml-cream) !important; }
.ml-constructor-callout__bg { position: absolute; inset: 0; z-index: 0; }
.ml-constructor-callout__bg picture, .ml-constructor-callout__bg img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ml-constructor-callout__bg::after { content: ""; position: absolute; inset: 0; background: rgba(18, 38, 59, .58); }
.ml-constructor-callout > :not(.ml-constructor-callout__bg) { position: relative; z-index: 1; }
.ml-constructor-callout h3, .ml-constructor-callout p { color: var(--ml-cream) !important; }
.ml-constructor-callout .ml-button { background: var(--ml-yellow) !important; border-color: var(--ml-yellow) !important; color: var(--ml-navy-deep) !important; }

/* ---- H-10 Кейси: tags yellow/powder, titles navy ---- */
.merch-case-card__tag, .merch-case-card .ml-tag { background: var(--ml-yellow) !important; color: var(--ml-navy-deep) !important; }

/* ---- H-12 / doc: CTA-секція з формою — rose, deep navy text, light-cream fields, navy submit ---- */
.ml-brief { background: var(--ml-rose) !important; color: var(--ml-navy-deep) !important; }
.ml-brief .ml-title, .ml-brief .ml-lead, .ml-brief .ml-kicker, .ml-brief h1, .ml-brief h2, .ml-brief h3, .ml-brief p { color: var(--ml-navy-deep) !important; }
.ml-brief .ml-kicker::before { background: var(--ml-navy-deep) !important; }
.ml-brief .merch-form, .ml-brief .dh-fbox { background: var(--ml-cream-light) !important; border-radius: 16px; }
.ml-brief .merch-form label { color: var(--ml-navy) !important; }
.ml-brief .ml-button:hover { background: var(--ml-navy-deep) !important; border-color: var(--ml-navy-deep) !important; color: var(--ml-cream) !important; }

/* ---- H-01 Hero on mobile: round 1 layered the copy over the photo with a navy gradient;
   with a cream hero (client doc) that left a blank cream block over the photo (measured 390px).
   Now: photo block on top (4:5, cover), cream copy below — no overlay text. ---- */
@media (max-width: 767px) {
	.ml-home-hero, .ml-home-hero__grid, .ml-home-hero__copy { min-height: 0 !important; }
	.ml-home-hero__grid { display: flex !important; flex-direction: column-reverse !important; }
	.ml-home-hero__media { position: relative !important; inset: auto !important; aspect-ratio: 4 / 5; width: 100%; max-height: 62svh; overflow: hidden; }
	.ml-home-hero__media::after { display: none !important; }
	.ml-home-hero__media img { width: 100%; height: 100%; object-fit: cover; }
	.ml-home-hero__copy { padding: 28px 16px 36px !important; }
	.ml-home-hero__copy .ml-display { max-width: none; }
	.ml-home-hero__actions .ml-button { font-size: 15px !important; }
}

/* 2026-09-25 — logged-out account (login / register / lost password): dof.css zeroes main#main-content padding for
   full-bleed heroes, so these forms touched the screen edges on phone/tablet. Give them the same side gutter as cart. */
@media (max-width: 1024px) {
	body.woocommerce-account:not(.logged-in) #main-content .entry-content {
		box-sizing: border-box;
		width: 100%;
		padding-inline: var(--dof-site-pad, 16px);
	}
}

/* «Отримати прайс» modal (merchlab_render_price_modal): contrast submit, readable eyebrow, errors/status (owner 28.09.2026). */
#dh-price-modal .dh-sample-form .dh-sample-form__submit {
	background: #1D446D;
	border-color: #1D446D;
	color: #FAEEC6;
	border-radius: 999px;
	font-weight: 700;
}
#dh-price-modal .dh-sample-form .dh-sample-form__submit:hover,
#dh-price-modal .dh-sample-form .dh-sample-form__submit:focus-visible {
	background: #12263B;
	border-color: #12263B;
	color: #FFE786;
}
#dh-price-modal .dh-sample-form .dh-sample-form__submit:disabled { opacity: .6; cursor: wait; }
#dh-price-modal .dh-sample-modal__eyebrow { color: #B05F66; }
#dh-price-modal .dh-sample-form input[type="email"] {
	width: 100%;
	padding: 11px 12px;
	border: 1px solid var(--dof-line, #e8d9ab);
	font: 400 14px/1.4 var(--dof-font-body, Inter), system-ui, sans-serif;
	color: var(--dof-ink, #12263b);
	background: var(--dof-bg-2);
}
#dh-price-modal .merch-form__error { display: block; margin-top: 4px; font-size: 12px; color: #B42318; }
#dh-price-modal .merch-form__error:empty { display: none; }
#dh-price-modal .merch-form__status:empty { display: none; }
#dh-price-modal .merch-form__status { margin-top: 12px; font-size: 13px; color: #B42318; }
#dh-price-modal .merch-form__status.is-success { color: #1D6B3A; }
#dh-price-modal .merch-form__trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
