/* ==========================================================
   Panoramic Feature Slider — .pf-* (scoped, standalone)
   Port of the SimplifyingAgricultureBanner section.

   Layout is driven by custom properties so Elementor's responsive
   controls can override any value per device. The media queries
   below only supply MOBILE-FIRST DEFAULTS; every one of them is
   replaceable from the Style tab.
   ========================================================== */

.pf-slider {
  /* -- Overlay -------------------------------------------------- */
  --pf-overlay: 85;              /* bottom stop strength (%) */
  --pf-overlay-mid: 35;          /* middle stop strength (%) */
  --pf-overlay-top: 0;           /* top stop strength (%) */
  --pf-overlay-bottom-c: color-mix(in srgb, #000000 85%, transparent);
  --pf-overlay-mid-c: color-mix(in srgb, #000000 35%, transparent);
  --pf-overlay-top-c: transparent;
  /* Flat colour wash over the whole frame, on top of the gradient above.
     Same idea as a container's Background Overlay: pick a colour, then dial
     the opacity. 0 keeps it off so an existing banner is untouched. */
  --pf-overlay-tint-c: #000000;
  --pf-overlay-tint-o: 0;

  /* -- Image ---------------------------------------------------- */
  --pf-img-fit: cover;
  /* The preset supplies a sensible pair of offsets. The Nudge controls
     each override exactly one axis, so a preset and a nudge compose
     instead of fighting (e.g. "top center" + horizontal nudge). */
  --pf-preset-x: 50%;
  --pf-preset-y: 50%;
  --pf-nudge-x: var(--pf-preset-x);
  --pf-nudge-y: var(--pf-preset-y);
  --pf-pos-x: var(--pf-nudge-x);
  --pf-pos-y: var(--pf-nudge-y);
  --pf-img-opacity: 1;
  --pf-brightness: 75;
  --pf-contrast: 100;
  --pf-saturate: 100;
  --pf-blur: 0px;
  --pf-fade-dur: 600ms;
  --pf-kb-scale: 1.08;
  /* Base zoom, multiplied into the Ken Burns animation so the two do
     not fight over the transform property. */
  --pf-zoom: 1;

  /* -- Typography animation ------------------------------------- */
  --pf-text-dur: 300ms;
  --pf-anim-shift: 24px;

  /* -- Layout --------------------------------------------------- */
  --pf-box-height: 400px;
  /* Height as a percentage of the width. 47 ≈ 21:9 (wide banner),
     56 ≈ 16:9, 75 ≈ 4:3, 100 = square. Kept in sync with the
     widget's own default so an unsaved widget and a saved one agree. */
  --pf-aspect-w: 47;
  --pf-nav-size: 40px;
  --pf-nav-radius: 9999px;
  --pf-nav-offset: 24px;

  position: relative;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  padding: 48px 24px; /* py-12 px-6 */
  min-height: var(--pf-box-height);
  /* Mandatory under aspect-ratio: with content-box the ratio sizes the
     CONTENT box and the padding is added on top of it, so the element
     grows wider than its parent and overflows the viewport. Themes that
     ship a global border-box reset hide this, but the widget cannot
     rely on that. */
  box-sizing: border-box;
  /* Never let an intrinsic child push the banner wider than its slot. */
  max-width: 100%;
}

/* ---- Height modes ------------------------------------------------
   The mode is toggled by a class the widget prints on the section.
   Elementor writes its custom properties in a STYLESHEET rule (not
   inline style), so an attribute selector such as [style*="..."]
   would never match — the class is the only reliable hook.
   ------------------------------------------------------------------ */

.pf-mode-height {
  height: var(--pf-box-height);
  min-height: var(--pf-box-height);
}

/* The frame keeps a constant crop on every device.
   --pf-aspect-w is a percentage of the width (47 ≈ 21:9), so the
   ratio is width÷height → 1 / (w/100). Defined after the base rule so
   it wins on equal specificity, and `min-height:0` releases the box
   height the base rule set.

   A wide ratio on a narrow screen collapses the frame to a couple of
   hundred pixels, which would crush the text. `--pf-aspect-floor` is a
   per-device floor that keeps the banner readable while still letting
   the ratio do the work on the devices where it fits. */
.pf-slider.pf-mode-aspect {
  min-height: var(--pf-aspect-floor, 0px);
  height: auto;
  aspect-ratio: 1 / calc(var(--pf-aspect-w) / 100);
}

@media (max-width: 1024px) {
  .pf-slider.pf-mode-aspect { --pf-aspect-floor: 380px; }
}

@media (max-width: 767px) {
  .pf-slider.pf-mode-aspect { --pf-aspect-floor: 420px; }
}

/* Source responsive ramp: lg:min-h-[560px], sm:py-16/px-10, lg:px-16.
   Elementor's responsive controls emit higher-specificity rules that
   override these when the user has values saved. */
@media (min-width: 640px) {
  .pf-slider {
    padding: 64px 40px; /* py-16 px-10 */
  }
}

@media (min-width: 1024px) {
  .pf-slider {
    padding: 64px 64px; /* py-16 px-16 */
  }
}

/* Very small screens: reclaim horizontal space the browser adds. */
@media (max-width: 479px) {
  .pf-slider {
    padding: 40px 20px;
  }
}

/* ---- Slide layer ---- */

.pf-slides {
  position: absolute;
  inset: 0;
}

/* The image layer is inset:0 by default. The Min Width / Min Height
   controls widen it past the frame for a "panoramic" crop, so the
   offsets have to be relaxed to let it grow past the edges.

   The selector is `.pf-slider .pf-slide`, NOT a bare `.pf-slide`, and that
   extra class is load-bearing. Elementor ships a global
   `.elementor img { height: auto; max-width: 100%; }`, which is specificity
   (0,1,1) — one class plus one type — and therefore BEATS a bare `.pf-slide`
   at (0,1,0). So `height: 100%` never applied: the photo was sized by its
   own intrinsic aspect ratio instead of filling the frame, and on a phone
   that left a 195px photo inside a 400px frame with `frame_background`
   showing underneath. Scoping to two classes (0,2,0) wins the comparison on
   the class count. This also protects `object-fit`, `object-position` and
   the composed `filter`, which Elementor's base rule would otherwise be
   free to clobber. */
.pf-slider .pf-slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* Every property here is variable-driven. The widget writes ONLY the
     variables, never a filter / object-fit shorthand, otherwise
     Elementor's higher-specificity rule would replace the whole
     declaration and silently disable the other controls. */
  object-fit: var(--pf-img-fit);
  object-position: var(--pf-pos-x) var(--pf-pos-y);
  opacity: 0;
  transition: opacity var(--pf-fade-dur) ease;
  filter:
    brightness(calc(var(--pf-brightness) * 1%))
    contrast(calc(var(--pf-contrast) * 1%))
    saturate(calc(var(--pf-saturate) * 1%))
    blur(var(--pf-blur));
  will-change: opacity, transform;
  backface-visibility: hidden;
  /* Zoom and the Ken Burns animation scale around the same point the
     crop is focused on, so enlarging never drifts the subject away. */
  transform-origin: var(--pf-pos-x) var(--pf-pos-y);
}

/* A slide only carries image opacity once it is the visible one,
   otherwise the crossfade would compound with the fade. */
.pf-slide.is-active {
  opacity: var(--pf-img-opacity);
  z-index: 1;
}

/* ---- Position preset → offsets -----------------------------------
   Elementor can only write the dropdown's raw value ("top center")
   into one custom property, so it is translated here into the two
   percentage offsets that object-position actually consumes. The
   nudges read these as their defaults.
   ------------------------------------------------------------------ */

.pf-pos-center-center { --pf-preset-x: 50%;  --pf-preset-y: 50%; }
.pf-pos-top-center    { --pf-preset-x: 50%;  --pf-preset-y: 0%; }
.pf-pos-bottom-center { --pf-preset-x: 50%;  --pf-preset-y: 100%; }
.pf-pos-center-left   { --pf-preset-x: 0%;   --pf-preset-y: 50%; }
.pf-pos-center-right  { --pf-preset-x: 100%; --pf-preset-y: 50%; }
.pf-pos-top-left      { --pf-preset-x: 0%;   --pf-preset-y: 0%; }
.pf-pos-top-right     { --pf-preset-x: 100%; --pf-preset-y: 0%; }
.pf-pos-bottom-left   { --pf-preset-x: 0%;   --pf-preset-y: 100%; }
.pf-pos-bottom-right  { --pf-preset-x: 100%; --pf-preset-y: 100%; }

/* ---- Per-slide focus point ---------------------------------------
   The widget prints data-focus / data-focus-mobile on any slide whose
   repeater row overrides the global position. These live on the <img>
   itself, so they beat the preset class on the section without needing
   !important, and they intentionally bypass the nudges.
   ------------------------------------------------------------------ */

/* The per-slide override is final: it sets the resolved offsets so a
   global nudge cannot drag the focus back off the subject. */
.pf-slide[data-focus] { --pf-nudge-x: initial; --pf-nudge-y: initial; }

.pf-slide[data-focus="center center"] { --pf-nudge-x: 50%;  --pf-nudge-y: 50%; }
.pf-slide[data-focus="top center"]    { --pf-nudge-x: 50%;  --pf-nudge-y: 0%; }
.pf-slide[data-focus="bottom center"] { --pf-nudge-x: 50%;  --pf-nudge-y: 100%; }
.pf-slide[data-focus="center left"]   { --pf-nudge-x: 0%;   --pf-nudge-y: 50%; }
.pf-slide[data-focus="center right"]  { --pf-nudge-x: 100%; --pf-nudge-y: 50%; }
.pf-slide[data-focus="top left"]      { --pf-nudge-x: 0%;   --pf-nudge-y: 0%; }
.pf-slide[data-focus="top right"]     { --pf-nudge-x: 100%; --pf-nudge-y: 0%; }
.pf-slide[data-focus="bottom left"]   { --pf-nudge-x: 0%;   --pf-nudge-y: 100%; }
.pf-slide[data-focus="bottom right"]  { --pf-nudge-x: 100%; --pf-nudge-y: 100%; }

/* Below 1024px the mobile override wins over the desktop focus. */
@media (max-width: 1024px) {
  .pf-slide[data-focus-mobile="center center"] { --pf-nudge-x: 50%;  --pf-nudge-y: 50%; }
  .pf-slide[data-focus-mobile="top center"]    { --pf-nudge-x: 50%;  --pf-nudge-y: 0%; }
  .pf-slide[data-focus-mobile="bottom center"] { --pf-nudge-x: 50%;  --pf-nudge-y: 100%; }
  .pf-slide[data-focus-mobile="center left"]   { --pf-nudge-x: 0%;   --pf-nudge-y: 50%; }
  .pf-slide[data-focus-mobile="center right"]  { --pf-nudge-x: 100%; --pf-nudge-y: 50%; }
  .pf-slide[data-focus-mobile="top left"]      { --pf-nudge-x: 0%;   --pf-nudge-y: 0%; }
  .pf-slide[data-focus-mobile="top right"]     { --pf-nudge-x: 100%; --pf-nudge-y: 0%; }
  .pf-slide[data-focus-mobile="bottom left"]   { --pf-nudge-x: 0%;   --pf-nudge-y: 100%; }
  .pf-slide[data-focus-mobile="bottom right"]  { --pf-nudge-x: 100%; --pf-nudge-y: 100%; }
}

/* Only the active slide gets the slow zoom, and it resets on leaving
   so the animation restarts cleanly on every cycle. */
.pf-kenburns-yes .pf-slide.is-active {
  animation: pf-kenburns var(--pf-kb-dur, 12s) ease-out forwards;
}

.pf-kenburns-yes .pf-slide:not(.is-active) {
  animation: none;
}

/* Without the Ken Burns effect the zoom control still has to apply. */
.pf-slide {
  transform: scale(var(--pf-zoom));
}

@keyframes pf-kenburns {
  from { transform: scale(var(--pf-zoom)); }
  to   { transform: scale(calc(var(--pf-zoom) * var(--pf-kb-scale))); }
}

/* ---- Overlay -----------------------------------------------------
   The z-index is load-bearing, not cosmetic.

   `.pf-slide.is-active` is a positioned element carrying `z-index: 1`, and
   neither `.pf-slides` nor `.pf-slider` creates a stacking context — so that
   slide is painted in the *parent* stacking context, above any positioned
   sibling left at `z-index: auto`. With no z-index of its own the overlay sat
   at the auto level and the opaque photo was painted straight over it: the
   gradient was emitted into the stylesheet, reported correctly by
   getComputedStyle(), and still completely invisible on the front end.

   2 sits above the slide (1) and below the content (10), which is the whole
   point — the wash has to darken the photo, never the text. */

.pf-overlay {
  position: absolute;
  inset: 0;
  z-index: 2;
  /* Bottom layer: the flat tint. `background-color` always paints behind
     `background-image`, so the gradient composes on top of it.

     The opacity slider is the ONLY thing that sets the alpha here. The
     `color-mix` fallback multiplies in whatever alpha the saved colour carries,
     which is fine until the picker hands us a fully transparent colour
     (`#00000000` — exactly what the live page has): 0 x anything is still 0, so
     the slider was dead. The relative-colour form below takes only the R/G/B
     channels and drives the alpha from the slider, so the control works no
     matter what the picker stored. */
  background-color: color-mix(
    in srgb,
    var(--pf-overlay-tint-c) calc(var(--pf-overlay-tint-o) * 1%),
    transparent
  );
  background-color: rgb(
    from var(--pf-overlay-tint-c) r g b / calc(var(--pf-overlay-tint-o) * 1%)
  );
  /* ---- Gradient ----
     The stops are pinned to the ends of the gradient axis (0% / 50% / 100%).
     They must NOT be positioned from the strength sliders.

     They used to be `calc(var(--pf-overlay) * 1%)` and
     `calc(var(--pf-overlay-top) * 1%)` — the sliders doubled as stop
     POSITIONS. With the shipped defaults that produced 85% / 50% / 35%, a
     DESCENDING list, and CSS clamps every stop to be >= the one before it, so
     all three collapsed onto 85%. The result was not a gradient at all: a flat
     fill with one hard edge, the middle stop eliminated, and on the diagonal
     options that hard edge sliced a wedge out of one corner — the "overlay does
     not cover the image" report.

     Opacity belongs to the colours alone: each one is already
     `color-mix(…, calc(var(--pf-overlay-*) * 1%), transparent)`, so the sliders
     still control strength — they just no longer move the stops. */
  background-image: linear-gradient(
    to top,
    var(--pf-overlay-bottom-c) 0%,
    var(--pf-overlay-mid-c) 50%,
    var(--pf-overlay-top-c) 100%
  );
  pointer-events: none;
}

/* ---- Content overlay ---- */

.pf-content {
  position: relative;
  z-index: 10;
  width: 100%;
  display: flex;
  flex-direction: row;              /* desktop: side by side */
  align-items: flex-end;
  justify-content: space-between;
  gap: 32px;
  pointer-events: none;
}

.pf-content__link {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: auto;
}

.pf-title {
  color: #ffffff;
  font-weight: 800;
  letter-spacing: -0.025em;
  max-width: 448px; /* max-w-md */
  line-height: 1.15;
  margin: 0;
  /* Fluid by default; the Typography group overrides this when set. */
  font-size: clamp(26px, 5.2vw, 48px);
  overflow-wrap: break-word;
}

.pf-side {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
}

.pf-caption {
  color: rgb(255 255 255 / 0.8);
  line-height: 1.625;
  max-width: 320px; /* max-w-xs */
  margin: 0;
  font-size: clamp(13px, 1.6vw, 15px);
  overflow-wrap: break-word;
}

/* ==========================================================
   TABLET  (<= 1024px)
   Stack the content — side-by-side needs horizontal room that a
   tablet in portrait simply does not have, and that mismatch was
   the main cause of the cramped look.
   ========================================================== */
@media (max-width: 1024px) {
  .pf-content {
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-end;
    gap: 28px;
  }

  .pf-title {
    max-width: 30ch;
  }

  .pf-side {
    width: 100%;
  }

  .pf-caption {
    max-width: 52ch;
  }
}

/* ==========================================================
   MOBILE  (<= 767px)
   Absolute positioning is what broke this layout before: on a short
   frame the browser resolved `space-between` on a flex container
   whose content was taller than the box, so the title and caption
   collided or overflowed. Content now flows as a single column
   anchored to the bottom, and `min-height` is free to grow.
   ========================================================== */
@media (max-width: 767px) {
  .pf-slider {
    align-items: flex-end;
    /* Never clip text on a narrow screen. */
    overflow: hidden;
  }

  .pf-content {
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-end;
    gap: 20px;
    height: auto;
  }

  .pf-title {
    max-width: none;
    line-height: 1.2;
    letter-spacing: -0.015em;
  }

  .pf-caption {
    max-width: none;
    font-size: 13px;
  }

  /* Tappable targets: keep the arrows reachable with a thumb. */
  .pf-nav {
    gap: 10px;
  }

  .pf-prev,
  .pf-next {
    min-width: 44px;
    min-height: 44px;
  }
}

/* ==========================================================
   NAV PLACEMENT
   The widget stamps the placement class on the <section> (`.pf-slider`),
   not on the nav — `render()` pushes it into `$classes`, which is the
   section's class list. Every rule here therefore has to hang off the
   section and descend to the nav.

   This used to read `.pf-nav:not(.pf-nav-inline)`, which asks whether the
   *nav* lacks `pf-nav-inline`. The nav never has it (the section does), so
   that selector matched unconditionally and the nav was always absolutely
   positioned — even in the default inline mode. An absolutely positioned
   child of a flex container resolves to the container's start corner, so
   the nav landed exactly on top of the caption: a measured 161x40px
   overlap, with the section's `pf-nav-inline` class sitting right there in
   the HTML doing nothing.
   ========================================================== */

.pf-nav {
  display: flex;
  align-items: center;
  gap: 12px;
  pointer-events: auto;
  position: relative;
  z-index: 6;
}

/* --- Placement variants ---------------------------------------- */

/* Inline mode, stated explicitly rather than left to the absence of a rule.
   A `position: absolute` at even slightly higher specificity — the old
   `.pf-nav:not(.pf-nav-inline)` form, or a page-level override — otherwise
   silently wins and the nav goes straight back on top of the caption. */
.pf-slider.pf-nav-inline .pf-nav {
  position: relative;
  z-index: 6;
  left: auto;
  right: auto;
  top: auto;
  bottom: auto;
  transform: none;
}

/* Pinned modes only. Inline (the default) keeps the nav in the flow, which
   is what lets it sit under the caption instead of over it. */
.pf-slider:not(.pf-nav-inline) .pf-nav {
  position: absolute;
  z-index: 20;
}

.pf-slider.pf-nav-bottom-left   .pf-nav { left: var(--pf-nav-offset);  bottom: var(--pf-nav-offset); }
.pf-slider.pf-nav-bottom-right  .pf-nav { right: var(--pf-nav-offset); bottom: var(--pf-nav-offset); }
.pf-slider.pf-nav-bottom-center .pf-nav { left: 50%; bottom: var(--pf-nav-offset); transform: translateX(-50%); }
.pf-slider.pf-nav-middle-left   .pf-nav { left: var(--pf-nav-offset);  top: 50%; transform: translateY(-50%); }
.pf-slider.pf-nav-middle-right  .pf-nav { right: var(--pf-nav-offset); top: 50%; transform: translateY(-50%); }
.pf-slider.pf-nav-top-left      .pf-nav { left: var(--pf-nav-offset);  top: var(--pf-nav-offset); }
.pf-slider.pf-nav-top-right     .pf-nav { right: var(--pf-nav-offset); top: var(--pf-nav-offset); }

/* Reserve room so a pinned row cannot sit on top of the text. The nav is a
   descendant of .pf-content, so the padding goes on that same element — it
   is the one that also holds the text. `render()` adds `pf-absnav-bottom`
   for every bottom-* placement, which is what we key off here. */
.pf-slider.pf-absnav-bottom > .pf-content {
  padding-bottom: calc(var(--pf-nav-size) + (var(--pf-nav-offset) * 2));
}

/* ---- Buttons ---- */

.pf-nav-shape-rounded { --pf-nav-radius: 12px; }
.pf-nav-shape-square  { --pf-nav-radius: 0; }

.pf-prev,
.pf-next {
  width: var(--pf-nav-size);
  height: var(--pf-nav-size);
  border-radius: var(--pf-nav-radius);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
  padding: 0;
  flex: none;
  touch-action: manipulation;
}

button.pf-prev,
button.pf-next {
  appearance: none;
  background: transparent;
  font: inherit;
  color: inherit;
  line-height: normal;
  overflow: visible;
  text-transform: none;
}

.pf-prev {
  border: 1px solid rgb(255 255 255 / 0.3);
  color: #ffffff;
  background-color: transparent;
}

.pf-prev:hover,
.pf-prev:focus-visible {
  background-color: rgb(255 255 255 / 0.2);
}

.pf-next {
  border: 0;
  color: #ffffff;
  background-color: rgb(27 77 46 / 0.9);
}

.pf-next:hover,
.pf-next:focus-visible {
  background-color: #1B4D2E;
}

.pf-icon {
  width: 16px;
  height: 16px;
  display: block;
}

.pf-counter {
  color: #ffffff;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  padding: 0 8px;
  white-space: nowrap;
}

.pf-prev:focus-visible,
.pf-next:focus-visible {
  outline: 2px solid #E3B32A;
  outline-offset: 2px;
}

/* ---- Directional text animation ---- */

.pf-anim-item {
  transition: opacity calc(var(--pf-text-dur) * 0.85) ease,
              transform var(--pf-text-dur) ease;
}

.pf-anim-item.pf-is-out {
  opacity: 0;
}

.pf-out-left {
  opacity: 0;
  transform: translateX(calc(var(--pf-anim-shift) * -1));
}

.pf-out-right {
  opacity: 0;
  transform: translateX(var(--pf-anim-shift));
}

/* Fade-only variant */
.pf-anim-fade .pf-out-left,
.pf-anim-fade .pf-out-right {
  transform: none;
}

/* Fade + zoom variant */
.pf-anim-zoom .pf-out-left,
.pf-anim-zoom .pf-out-right {
  transform: scale(0.94);
}

/* No animation variant */
.pf-anim-none .pf-anim-item {
  transition: none !important;
}

.pf-anim-none .pf-out-left,
.pf-anim-none .pf-out-right {
  transform: none;
}

.pf-no-anim {
  transition: none !important;
}

/* ---- Swipe affordance ---- */

.pf-swipeable .pf-slides {
  touch-action: pan-y;
}

.pf-dragging,
.pf-dragging .pf-slide {
  cursor: grabbing;
}

/* ---- Reduced motion ---- */

@media (prefers-reduced-motion: reduce) {
  .pf-slide,
  .pf-anim-item,
  .pf-prev,
  .pf-next {
    transition: none !important;
  }

  .pf-kenburns-yes .pf-slide.is-active {
    animation: none !important;
  }
}
