/**
 * Modeser Products List Widget — a long-form catalog page. Every structural
 * block is its OWN top-level flex div, all flat siblings directly under
 * .mdsproduct-list (no per-category wrapper): a category heading div, then
 * for each product — a product-row div (image/content split) — an info-box
 * div (How to Use/Good to Know/Ingredients split), and a divider div, each
 * one separate, repeating in that order (see ProductsList::render()/
 * renderProduct()).
 */

.mdsproduct-list-empty {
  opacity: 0.7;
}

/*
 * Per-element "Animation" (Image/Title/Slogan/Description/Button/"What It
 * Does"/Info Box Style — see HasScrollEntranceAnimation.php) pre-hide state,
 * a direct copy of Elementor core's own `.elementor-invisible{visibility:
 * hidden}` — `visibility` rather than `opacity` specifically because
 * several of Elementor's own entrance keyframes (the "Slide" family)
 * animate `transform` only, never `opacity`; an opacity-based hide would
 * never get overridden by the keyframe itself. Removed by
 * scroll-entrance-animation.js the instant the animation starts.
 */
.mdsproduct-scroll-anim-pending {
  visibility: hidden;
}

/*
 * NOTE: deliberately NO `animation-fill-mode` override here (unlike
 * product-card.css's hover-animation fix, which genuinely needs `forwards`
 * since a hover-out removes the trigger class). Two reasons a fill-mode
 * override is unnecessary — and actively harmful — for THIS animation:
 *
 * 1. Delay is applied in JS via `setTimeout` (scroll-entrance-animation.js),
 *    not CSS `animation-delay` — `.animated` + the animation-name class are
 *    only ever added together, at the moment the delay has already elapsed,
 *    so there is no "waiting" window during which a backwards fill would be
 *    needed to hold the 0% keyframe.
 * 2. Every one of Elementor's native Entrance Animations (fadeIn*, zoomIn*,
 *    slideIn*, etc.) resolves its 100% keyframe to the element's natural,
 *    un-animated CSS state (`opacity:1; transform:none`) — so even with NO
 *    fill-mode, the instant the animation ends the element reverts to
 *    exactly what a held "forwards" frame would have shown anyway.
 *
 * A persistent `animation-fill-mode` (previously `both !important`) on an
 * element that ALSO has `border-radius` + `overflow:hidden` on itself (e.g.
 * `.mdsproduct-list-info-box`, see ProductsList::register_info_box_style_
 * controls()) keeps that element pinned to its own GPU-composited layer
 * indefinitely, even after the keyframe has visually settled — some
 * browsers (Chrome/Blink in particular) fail to apply the border-radius
 * clip mask cleanly on that composited layer, showing a thin white seam at
 * the rounded corners. Removing the fill-mode override fixes this with no
 * animation regression, per the two reasons above.
 */

/*
 * Flex row — its two direct children (.mdsproduct-list-category-badge-wrap
 * and .mdsproduct-list-category-title-wrap) lay out side by side; each
 * wraps a single element (img / heading tag) rather than being a flex item
 * itself, purely so Content > Category Header's "CSS Classes" control has
 * a dedicated element (the title wrapper) to target without also reaching
 * the badge.
 */
.mdsproduct-list-category-header {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 60px;
  margin-bottom: 30px;
}

.mdsproduct-list-category-header:first-child {
  margin-top: 0;
}

.mdsproduct-list-category-badge-wrap {
  display: block;
  flex-shrink: 0;
}

.mdsproduct-list-category-badge {
  display: block;
  width: 48px;
  height: 48px;
  object-fit: contain;
}

.mdsproduct-list-category-title {
  /*
   * No font-size/font-weight here on purpose — Content > Category Header's
   * "HTML Tag" control (h1/h2/h3) lets this heading inherit the theme's or
   * Elementor's own Site Settings typography for that tag; a static
   * font-size/weight here would silently override it regardless of which
   * tag is chosen. Style > Category Header's own Typography control still
   * lets a user override per-instance if they want to, same as before.
   */
  margin: 0;
}

.mdsproduct-list-product {
  display: flex;
  align-items: flex-start;
  gap: 32px;
  margin-top: 30px;
}

/*
 * Only reset when it's ALSO the category's first child (i.e. no header
 * rendered before it — an "uncategorized" group, or Show Category Header
 * turned off): when a header IS present, the header's own bottom spacing
 * already separates it from this row, so the two margins are meant to
 * stack, not collapse to one.
 */
.mdsproduct-list-category > .mdsproduct-list-product:first-child {
  margin-top: 0;
}

.mdsproduct-list-product-media {
  position: relative;
  flex: 0 0 auto;
  width: 33%;
}

.mdsproduct-list-product-image {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
}

.mdsproduct-list-product-content {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.mdsproduct-list-product-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.mdsproduct-list-product-title {
  /*
   * Flex-grows to fill the row's remaining width (button stays
   * flex-shrink:0 pinned to its own content size) so the Title Style >
   * Alignment control's `text-align` has a box wide enough to actually
   * move text within — a title with default (Left) alignment renders
   * identically either way, since its text already starts flush left.
   *
   * No font-size/font-weight here on purpose — Content > Content's "Title
   * HTML Tag" control (h1/h2/h3) lets this heading inherit the theme's or
   * Elementor's own Site Settings typography for that tag; a static
   * font-size/weight here would silently override it regardless of which
   * tag is chosen. Style > Title Style's own Typography control still lets
   * a user override per-instance if they want to, same as before.
   */
  flex: 1 1 auto;
  margin: 0;
}

/*
 * Wraps one .mdsproduct-list-product-button PER variation (see
 * ProductsList::renderProduct()'s $variation_buttons) in place of the
 * single base-product button — itself the flex item sibling to the
 * title inside .mdsproduct-list-product-header, so it needs the same
 * flex-shrink:0 the single button relies on to not get squeezed by the
 * title's own flex:1 1 auto.
 */
.mdsproduct-list-product-buttons {
  display: flex;
  flex-wrap: wrap;
  flex-shrink: 0;
  gap: 8px;
}

.mdsproduct-list-product-button {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #ffffff;
  background-color: #1a1a1a;
  padding: 10px 20px;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.2s ease, color 0.2s ease;
}

.mdsproduct-list-product-button:hover {
  background-color: #3f3f3f;
  color: #ffffff;
}

/* Only takes effect once an icon is actually rendered next to the text
   (see ProductsList::buttonInnerHtml()) — `gap` has no visible effect on
   a single-child flex container. */
.mdsproduct-list-product-button-icon {
  display: inline-flex;
  align-items: center;
  font-size: 1em;
  line-height: 1;
}

.mdsproduct-list-product-button-icon svg {
  width: 1em;
  height: 1em;
  fill: currentColor;
}

.mdsproduct-list-product-slogan {
  margin: 0;
  font-weight: 600;
}

.mdsproduct-list-product-description,
.mdsproduct-list-product-description p {
  margin: 0;
}

.mdsproduct-list-product-description > *:last-child {
  margin-bottom: 0;
}

/*
 * Label + list used to be direct flex children of .mdsproduct-list-product-
 * content, getting the gap between them "for free" from its own `gap`
 * (Style > Layout > "Content Item Gap"). Now wrapped together so the whole
 * "What It Does" block can carry its own scroll Animation setting (see
 * ProductsList::renderProduct()) — `--mdsproduct-content-gap` (set by that
 * same "Content Item Gap" control) reproduces the identical spacing here,
 * responsive breakpoints included, instead of a hardcoded duplicate value.
 */
.mdsproduct-list-product-wid {
  display: flex;
  flex-direction: column;
  gap: var(--mdsproduct-content-gap, 10px);
}

.mdsproduct-list-product-wid-label {
  margin: 0;
  font-weight: 600;
}

.mdsproduct-list-product-wid-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 0;
  padding-left: 20px;
}

.mdsproduct-list-product-wid-list li {
  list-style: disc;
}

/*
 * Info Box background/border/radius/padding/gap all come from Style > Info
 * Box Style controls (Group_Control_Background + Group_Control_Border, same
 * pattern as ProductsShowcase's Image 1 Overlay) — this fallback color only
 * shows before the admin sets one of their own.
 */
.mdsproduct-list-info-box {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  background-color: #1a2436;
  border-radius: 16px;
  padding: 24px;
  margin-top: 4px;
}

/*
 * Style > Info Box — Background Overlay targets this ::after rather than
 * the box's own background (set above / via Info Box Style) — a second
 * layer is needed to tint/texture the base fill without replacing it, same
 * technique as ProductsShowcase's Image 1/2 Overlay. `content` is required
 * for the pseudo to render; everything the Group_Control_Background
 * 'selectors' don't cover is static base CSS here. `z-index: 0` keeps it
 * above the box's own background/border but below the actual column
 * content, which gets its own stacking context below.
 */
.mdsproduct-list-info-box::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.mdsproduct-list-info-col {
  position: relative;
  z-index: 1;
  flex: 1 1 0;
  min-width: 160px;
}

/*
 * The flanking lines either side of the label — --mdsproduct-info-heading-
 * line is set by the "Line Color" control (Style > Info Box Title Style);
 * a CSS custom property rather than a second 'selectors' rule since it's
 * shared by both ::before and ::after. Width/Height default here (30px/1px)
 * match that same section's own control defaults — Elementor's generated
 * per-instance CSS always overrides these once the widget actually renders
 * through Elementor, this is only the static fallback.
 */
.mdsproduct-list-info-heading {
  --mdsproduct-info-heading-line: rgba(255, 255, 255, 0.15);
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px 0;
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.mdsproduct-list-info-heading::before,
.mdsproduct-list-info-heading::after {
  content: '';
  flex: 0 0 auto;
  width: 30px;
  height: 1px;
  background-color: var(--mdsproduct-info-heading-line);
}

/*
 * "Show Line" off, or "Position" set to only one side (Style > Info Box
 * Title Style) — plain PHP-rendered classes (infoBoxHeadingLineClass()),
 * not Elementor-generated CSS, so there's no specificity/load-order
 * question against the base rule above: these are in the SAME stylesheet,
 * declared after it, and win on that alone.
 */
.mdsproduct-list-info-heading--no-line::before,
.mdsproduct-list-info-heading--no-line::after {
  display: none;
}

.mdsproduct-list-info-heading--line-before::after {
  display: none;
}

.mdsproduct-list-info-heading--line-after::before {
  display: none;
}

.mdsproduct-list-info-text,
.mdsproduct-list-info-text p {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.5;
}

.mdsproduct-list-info-text > *:last-child {
  margin-bottom: 0;
}

/*
 * Divider — ported from Elementor core's own Divider widget CSS
 * (`elementor/assets/css/widget-divider.min.css`), renamed to our own
 * `--mdsproduct-divider-*` custom properties/classes. Two independent
 * rendering paths share these properties:
 *   1. Plain CSS border (Style: Solid/Double/Dotted/Dashed) — the default.
 *   2. SVG pattern via `mask-image` (every other Style — Curly/Wavy/
 *      Arrows/Tribal/etc.), switched on by the `--pattern` modifier class.
 * Both `--pattern` and `--has-element` (rendered when "Add Element" isn't
 * "None") are added directly on THIS SAME `.mdsproduct-list-divider`
 * element by ProductsList::buildDividerHtml() — no `prefix_class`/widget-
 * wrapper split (an earlier version used one, and the two modifier classes
 * ended up on different elements without a descendant combinator between
 * them, silently no-opping the pattern rendering — keeping everything
 * PHP-rendered on one element removes that whole class of mistake).
 * "Add Element" (None/Text/Icon) — when NOT None, the mask/border moves
 * from the separator itself onto its own `::before`/`::after` pseudo-
 * elements, leaving room in the middle for the icon/text.
 */
.mdsproduct-list-divider {
  /*
   * `--mdsproduct-divider-border-style`/`-color` deliberately NOT given a
   * fallback value here, unlike the properties below — the "Color"/"Style"
   * controls (Style > Divider Style) already have their OWN 'default' and
   * always generate a rule setting these on the WIDGET WRAPPER (an
   * ancestor). Redeclaring the same properties here — even to the exact
   * same values — would make THIS element's OWN declaration win over that
   * inherited one regardless of what the user picks (an element's own
   * declared custom property value always beats an inherited one,
   * independent of source order/specificity), permanently masking both
   * controls. Confirmed live: this was exactly why "Color" appeared to do
   * nothing.
   */
  --mdsproduct-divider-border-width: 1px;
  --mdsproduct-divider-element-size: 20px;
  --mdsproduct-divider-element-spacing: 10px;
  --mdsproduct-divider-pattern-height: 24px;
  --mdsproduct-divider-pattern-size: 20px;
  --mdsproduct-divider-pattern-url: none;
  --mdsproduct-divider-pattern-repeat: repeat-x;
  display: flex;
  margin-top: 30px;
}

.mdsproduct-list-divider-separator {
  direction: ltr;
  display: flex;
  margin: 0;
  width: 100%;
}

.mdsproduct-list-divider:not(.mdsproduct-list-divider--has-element) .mdsproduct-list-divider-separator {
  border-block-start: var(--mdsproduct-divider-border-width) var(--mdsproduct-divider-border-style) var(--mdsproduct-divider-color);
}

.mdsproduct-list-divider--has-element .mdsproduct-list-divider-separator {
  align-items: center;
}

.mdsproduct-list-divider--has-element .mdsproduct-list-divider-separator::before,
.mdsproduct-list-divider--has-element .mdsproduct-list-divider-separator::after {
  content: '';
  display: block;
  flex-grow: 1;
  border-block-start: var(--mdsproduct-divider-border-width) var(--mdsproduct-divider-border-style) var(--mdsproduct-divider-color);
}

.mdsproduct-list-divider-element {
  flex-shrink: 0;
  margin: 0 var(--mdsproduct-divider-element-spacing);
  font-size: var(--mdsproduct-divider-element-size);
  line-height: 1;
  color: var(--mdsproduct-divider-color);
}

.mdsproduct-list-divider-text {
  max-width: 95%;
}

/* Pattern mode: mask-image replaces the plain border, on the separator
   itself when there's no element, or on its flanking pseudo-elements when
   there is. `--mdsproduct-divider-pattern-size`/`-repeat` are set inline
   per-instance (ProductsList::buildDividerHtml(), computed from the chosen
   style's own metadata), the values here are just the pre-JS/PHP-render
   fallback. */
.mdsproduct-list-divider--pattern:not(.mdsproduct-list-divider--has-element) .mdsproduct-list-divider-separator,
.mdsproduct-list-divider--pattern.mdsproduct-list-divider--has-element .mdsproduct-list-divider-separator::before,
.mdsproduct-list-divider--pattern.mdsproduct-list-divider--has-element .mdsproduct-list-divider-separator::after {
  border-block-start: 0;
  background-color: var(--mdsproduct-divider-color);
  -webkit-mask-image: var(--mdsproduct-divider-pattern-url);
  mask-image: var(--mdsproduct-divider-pattern-url);
  -webkit-mask-repeat: var(--mdsproduct-divider-pattern-repeat);
  mask-repeat: var(--mdsproduct-divider-pattern-repeat);
  -webkit-mask-size: var(--mdsproduct-divider-pattern-size) 100%;
  mask-size: var(--mdsproduct-divider-pattern-size) 100%;
  min-height: var(--mdsproduct-divider-pattern-height);
  width: 100%;
}

/*
 * .mdsproduct-list-product-media's own reflow to 100% width below this
 * breakpoint is NOT set here — it's the "Image Column Width" control's own
 * tablet_default (Style > Layout) now, not a static rule. A plain class
 * selector in this stylesheet can never reliably out-specificity
 * Elementor's generated `{{WRAPPER}} .mdsproduct-list-product-media` rule
 * (2 classes) once that control has ANY value (always true, even at its
 * own plain 'default') — confirmed live, a rule here USED to exist and was
 * silently dead the moment a custom Image Column Width was set.
 */
@media (max-width: 1024px) {
  .mdsproduct-list-product {
    flex-direction: column;
  }

  .mdsproduct-list-info-box {
    flex-direction: column;
  }

  /*
   * Title + Buy Now button (Content > Content) — no Elementor control
   * targets this element's `flex-direction`/`align-items`, only `.mdsproduct-
   * list-product-header`'s children get their OWN color/typography/margin/
   * padding rules elsewhere — so a plain static override here is safe
   * (nothing to lose a specificity fight against, unlike the Image Column
   * Width bug above).
   */
  .mdsproduct-list-product-header {
    flex-direction: column;
    align-items: flex-start;
  }

  /*
   * `align-items: flex-start` above shrinks every row child to its own
   * content width in this stacked (column) layout — including the title,
   * which would otherwise make Title Style > Alignment's `text-align`
   * invisible here (nothing to align text WITHIN). `align-self: stretch`
   * opts the title back into full-row-width (button keeps its own
   * content-hugging width via flex-shrink:0, unaffected).
   */
  .mdsproduct-list-product-title {
    align-self: stretch;
  }
}
