/**
 * Single-product layout — un-toolkit.
 *
 * Two desktop layouts from ONE Elementor template, switched by the body signal
 * class `un-no-wheel` (added in includes/color-meta.php when the ChromaLab block
 * renders nothing). A single CSS-grid container reflows its children via named
 * grid-areas; no widget is duplicated.
 *
 * Target Elementor structure — the "Données produits" container gets the class
 * `un-product-grid` and holds these children (each an Elementor widget or a
 * sub-container), tagged with an area class:
 *
 *   .un-area-media   left block: gallery + price + add-to-cart
 *   .un-wheel-col    the "UN ChromaLab — Product" widget (wheel + swatches)
 *   .un-area-req     the "UN - Produit requis" widget
 *   .un-area-tabs    the product data tabs (The7 / UN product content)
 *   .un-spec-col     the "UN - Fiche technique" widget
 *
 * The page title / breadcrumb stay in their own block ABOVE the grid.
 *
 * BOXED vs FULL-WIDTH — the container works EITHER way, so it can match the
 * category-archive template (boxed) without special settings. Elementor wraps a
 * *boxed* container's children in an extra `.e-con-inner`; a *full-width* one
 * has none. The real grid host is therefore:
 *     boxed      → `.un-product-grid > .e-con-inner`  (Elementor centers this
 *                  at the site content width for free — NO max-width needed)
 *     full-width → `.un-product-grid` itself          (spans its parent)
 * Every rule below addresses the host through this token:
 *     :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner)
 * The `:not(:has(> .e-con-inner))` guard keeps the grid OFF the outer element in
 * boxed mode — putting it there collapses the lone `.e-con-inner` into column 1
 * (the classic "everything squished on the left" break). The area children sit
 * one level under whichever host matched, so `HOST > .un-area-*` resolves in
 * both modes. (`:has()`/`:is()` support already assumed — used throughout.)
 *
 * See custom-classes-helpers.md for the full build recipe.
 */

/* We own this host's layout outright. Elementor generates flex rules for
 * `.e-con.e-flex` (specificity 0,2,0) that would otherwise force its own
 * direction; `!important` lets our grid/flex win deterministically, so the
 * container's own "Disposition / Direction" settings never matter. */
body :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) {
	/* Tunables (override per-placement in Elementor custom CSS if needed). */
	--unpl-gap: 40px;
	--unpl-col-mid: minmax(260px, 0.9fr); /* ChromaLab wheel column */
	--unpl-col-side: minmax(280px, 1fr);  /* media / spec columns     */

	display: grid !important;
	gap: var(--unpl-gap);
	align-items: start;
}

/* Three breakpoints, each isolated in its own media query so they never fight
 * on specificity: desktop (>1024) grid, tablet (768–1024) 2-col grid, mobile
 * (≤767) single column. Drawers are active ≤1024 (tablet + mobile).
 *
 * Line-based placement (not grid-template-areas) lets the stacked side column
 * AUTO-FLOW: when "Produit requis" is absent, the block below rises to the top
 * instead of leaving an empty reserved row. */

/* DEFAULT = a SINGLE content row + a full-width row below, so the gap between
 * the content and the description is never doubled (the old 2-row span left an
 * empty middle row when "Produit requis" was absent, stacking two row-gaps).
 * When a real Produit requis IS rendered (the widget outputs `.un-req`), `:has()`
 * switches to a 2-row layout stacking req over the fiche, media/wheel spanning. */

/* ============================ DESKTOP (>1024) ============================ */
@media (min-width: 1025px) {
	/* ---- WITH wheel: media | wheel(+swatches) | fiche ; tabs full width ---- */
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) {
		grid-template-columns: var(--unpl-col-side) var(--unpl-col-mid) var(--unpl-col-side);
	}
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-media { grid-column: 1; grid-row: 1; }
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-wheel-col  { grid-column: 2; grid-row: 1; min-width: 0; }
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-req   { grid-column: 3; grid-row: 1; }
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-spec-col   { grid-column: 3; grid-row: 1; }
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-tabs  { grid-column: 1 / -1; grid-row: 2; min-width: 0; }

	/* req present → 2 rows: req over fiche, media/wheel span both, tabs row 3 */
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner):has(> .un-area-req .un-req) > .un-area-media { grid-row: 1 / 3; }
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner):has(> .un-area-req .un-req) > .un-wheel-col  { grid-row: 1 / 3; }
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner):has(> .un-area-req .un-req) > .un-area-req   { grid-row: 1; }
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner):has(> .un-area-req .un-req) > .un-spec-col   { grid-row: 2; }
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner):has(> .un-area-req .un-req) > .un-area-tabs  { grid-row: 3; }

	/* ---- WITHOUT wheel: media | fiche ; description (tabs) full width ------ */
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) {
		grid-template-columns: var(--unpl-col-side) var(--unpl-col-side);
	}
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-wheel-col  { display: none; }
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-media { grid-column: 1; grid-row: 1; }
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-req   { grid-column: 2; grid-row: 1; }
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-tabs  { grid-column: 2; grid-row: 1; min-width: 0; }
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-spec-col   { grid-column: 1 / -1; grid-row: 2; }

	/* req present → media spans, req over tabs in col 2, fiche full width row 3 */
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner):has(> .un-area-req .un-req) > .un-area-media { grid-row: 1 / 3; }
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner):has(> .un-area-req .un-req) > .un-area-req   { grid-row: 1; }
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner):has(> .un-area-req .un-req) > .un-area-tabs  { grid-row: 2; }
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner):has(> .un-area-req .un-req) > .un-spec-col   { grid-row: 3; }
}

/* ============================ TABLET (768–1024) ========================= *
 * 2 columns: media | second block (wheel + swatches if wheel, else Produit
 * requis), everything else full width below. The wheel renders INLINE here —
 * only the Fiche technique uses its drawer on tablet. */
@media (min-width: 768px) and (max-width: 1024px) {
	body :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) {
		grid-template-columns: 1fr 1fr;
	}

	/* WITH wheel: media | swatches ; the ChromaLab button tucks under the swatches
	 * (col 2), the rest is full width. The chroma trigger is the one right after
	 * the wheel column in the DOM. */
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-media { grid-column: 1; grid-row: 1; }
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-wheel-col  { grid-column: 2; grid-row: 1; min-width: 0; }
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-req,
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-tabs,
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-spec-col,
	body:not(.un-no-wheel) :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-drawer-trigger { grid-column: 1 / -1; }
	/* Wheel renders inline on tablet, so its ChromaLab reveal button isn't needed. */
	body :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-wheel-col + .un-drawer-trigger { display: none; }

	/* WITHOUT wheel: media | Produit requis */
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-wheel-col  { display: none; }
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-media { grid-column: 1; grid-row: 1; }
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-req   { grid-column: 2; grid-row: 1; }
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-area-tabs,
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-spec-col,
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-drawer-trigger { grid-column: 1 / -1; }
}

/* ============================ MOBILE (≤767) ============================= *
 * Single column. Order follows the Elementor navigator order of the grid's
 * direct children — arrange them as you want them read on phones. */
@media (max-width: 767px) {
	body :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) {
		display: flex !important;
		flex-direction: column !important;
		gap: var(--unpl-gap);
		/* Every block spans the column. Without this the container's own Elementor
		 * "align items: start" (a more specific rule, hence !important) sizes each
		 * block to its content: the tabs box narrowed whenever the active panel
		 * held short text. */
		align-items: stretch !important;
	}

	/* Wheel UI lives in its drawer on phones; the swatches stay inline. Gated on a
	 * wired drawer (body class from un-product-layout.js) so a page without a
	 * ChromaLab drawer keeps its wheel inline. */
	body.un-drawer-ready--chromalab .un-product-grid .chromalab-product .chromalab {
		display: none;
	}
	/* The wrap is now empty (0 height), so its bottom margin collapsed through it
	 * and surfaced as a stray 16px ABOVE the swatches. Back when it moves to the
	 * drawer, since the rule is scoped to the grid. */
	body.un-drawer-ready--chromalab .un-product-grid .chromalab-product__wheel-wrap {
		margin-bottom: 0;
	}
}

/* ===== Fiche drawer: tablet + mobile (≤1024). Wheel drawer: mobile only ==== */
@media (max-width: 1024px) {
	/* Show the wheel column again (for its swatches) even when un-no-wheel hides
	 * it on desktop — but only if it actually has a block. */
	body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-wheel-col:not(:empty) {
		display: block;
	}

	/* Fiche technique inline preview: show only the FIRST section (clean, no
	 * fade-out); the full fiche opens in its drawer via the button. */
	:is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-spec-col[data-unpl-clamp] .un-ontology-details__group:not(:first-child) {
		display: none;
	}
}

/* --- Product tabs titles: Accent S on phones/tablets, Accent M above ------- *
 * The tabs widget is set to the global "Accent S" typography, and an Elementor
 * global can't vary per device. Above the Elementor tablet breakpoint (900px),
 * the Accent S variables are re-pointed at Accent M for the tab titles only,
 * so both styles stay editable from the kit. */
@media (min-width: 901px) {
	.un-area-tabs .woocommerce-tabs ul.wc-tabs {
		--e-global-typography-el_f_accent_s-font-family: var(--e-global-typography-el_f_accent_m-font-family);
		--e-global-typography-el_f_accent_s-font-size: var(--e-global-typography-el_f_accent_m-font-size);
		--e-global-typography-el_f_accent_s-font-weight: var(--e-global-typography-el_f_accent_m-font-weight);
		--e-global-typography-el_f_accent_s-line-height: var(--e-global-typography-el_f_accent_m-line-height);
		--e-global-typography-el_f_accent_s-letter-spacing: var(--e-global-typography-el_f_accent_m-letter-spacing);
	}
}

/* --- Drawer triggers (reveal buttons) ------------------------------------ *
 * Buttons with class `un-drawer-trigger`. Hidden on desktop; shown ≤1024px. */
.un-drawer-trigger {
	display: none;
}

@media (max-width: 1024px) {
	.un-drawer-trigger {
		display: block;
	}

	/* Each trigger reads as the footer of the block it opens, not as a section of
	 * its own: pull it up out of the grid gap (40px, which stacked on the swatches'
	 * reserved variation-name line) to a tight --unpl-trigger-gap below its block. */
	:is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > :is(.un-wheel-col, .un-spec-col) + .un-drawer-trigger {
		margin-top: calc(var(--unpl-trigger-gap, 12px) - var(--unpl-gap));
	}
	/* The swatches already end on a reserved variation-name line (~36px with its
	 * margin), which is breathing room enough: no extra gap on the ChromaLab one. */
	:is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-wheel-col + .un-drawer-trigger {
		--unpl-trigger-gap: 0px;
	}
}

/* Phones (Elementor mobile breakpoint, 600px): triggers span the full width.
 * The widget wrapper shrink-wraps as a flex item and the The7 button is
 * inline-flex, so both levels need stretching; Elementor's own width control
 * doesn't reach the inner link. */
@media (max-width: 600px) {
	:is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-drawer-trigger {
		align-self: stretch;
		width: 100%;
	}
	.un-product-grid .un-drawer-trigger .elementor-button {
		width: 100%;
		justify-content: center;
	}

	/* Product tabs row. A title that wraps keeps the box width it was squeezed
	 * to, not its wrapped text width, so "Utilisations principales" floated in
	 * wide empty margins while "Application" sat on bare padding. Each tab now
	 * starts from its narrowest text width (words stacked) and the row's spare
	 * width is shared equally, so every title gets the same space around it. */
	.un-area-tabs .woocommerce-tabs ul.wc-tabs > li {
		flex: 1 1 auto;
		width: min-content;
	}
	.un-area-tabs .woocommerce-tabs ul.wc-tabs > li > a {
		display: block;
		text-align: center;
	}
}

/* No wheel on this product → nothing for the ChromaLab reveal button to open.
 * Hide that button specifically (it's the sibling right after the wheel column);
 * the Fiche technique trigger, a different sibling, stays visible. */
body.un-no-wheel :is(.un-product-grid:not(:has(> .e-con-inner)), .un-product-grid > .e-con-inner) > .un-wheel-col + .un-drawer-trigger {
	display: none;
}

/* Off-Canvas slots: empty containers the user places inside each Off-Canvas
 * widget. un-product-layout.js moves the wheel UI / clones the full fiche into
 * the matching slot on mobile and adds `is-filled`. The relocated wheel UI is
 * outside `.un-product-grid`, so the inline-hide rule no longer applies to it;
 * this `!important` is belt-and-braces in case of cascade surprises. */
.un-drawer-slot.is-filled .chromalab,
.un-drawer-slot.is-filled .un-ontology-details {
	display: block !important;
}
.un-drawer-slot {
	min-width: 0;
}

/* Drawer content framing. The slot is a direct child of Elementor's block-level
 * `.e-off-canvas__content`; we own the gutter here so it's guaranteed symmetric
 * on every side (no stray margin on the side the panel opens from, whatever the
 * slot's own padding). Content starts at the top, right under the drawer
 * header (title + close) and its divider, and a long swatch grid scrolls. The
 * gutter matches the popup drawers' container (40px 32px, see the design
 * charter). Scoped via :has() so only our two drawers are touched. */
.e-off-canvas__content:has(> .un-drawer-slot--chromalab),
.e-off-canvas__content:has(> .un-drawer-slot--fiche) {
	display: flex;
	flex-direction: column;
	padding: 40px 32px;
	box-sizing: border-box;
}

.e-off-canvas__content > .un-drawer-slot--chromalab,
.e-off-canvas__content > .un-drawer-slot--fiche {
	margin: 0;
	width: 100%;
	padding: 0 !important;    /* gutter is owned by the panel body above — no double/asymmetric padding */
}

/* Fit the wheel row (title + wheel + lightness) to the drawer width. The
 * Elementor wheel size is a fixed px (inline --cl-wheel-max) that overflowed a
 * narrow drawer and made the panel scroll sideways. The
 * slot is an inline-size container, so 100cqw is a definite width (no
 * percentage loop, see chroma-filter.css); 120px = title + gaps + lightness.
 * chroma-product.js rebuilds the wheel when its box width changes. */
.un-drawer-slot--chromalab {
	container-type: inline-size;
}

/* Same fit for the wheel inline in the product grid: the wheel column narrows
 * on small desktops (278px at 1025) while the wheel stayed a fixed px and
 * overflowed it. The wrap is a block that spans the column, so 100cqw is
 * definite; 140px = vertical title + gaps + lightness slider, measured. The
 * "Wheel max size" control is now a cap, the column decides below it. Scoped
 * to the grid: once moved to the drawer, the drawer rule above applies. */
.un-product-grid .chromalab-product__wheel-wrap {
	container-type: inline-size;
}
.un-product-grid .chromalab-product__wheel-wrap .chromalab__wheel-wrapper {
	width: min(var(--cl-wheel-max, 200px), calc(100cqw - 140px));
}
.un-drawer-slot--chromalab .chromalab--in-product .chromalab__wheel-wrapper {
	width: min(var(--cl-wheel-max, 200px), calc(100cqw - 120px));
}
