/*!
 * Gerard Slider — component styles.
 * Ported from the structural wireframe (v7). Retheme by overriding the
 * --gs-* tokens below (from the theme, or on Sliders → Appearance);
 * component rules shouldn't need editing.
 * Requires Swiper's swiper-bundle.min.css to load first. On Automatic.css 4
 * sites, gerard-slider-acss.css loads after this file and maps the tokens to
 * ACSS variables.
 */

/* ============================================================
   DESIGN TOKENS

   Naming: --gs-{element}-{property}[--{modifier}]
   - element: the BEM element styled, spelled as in the markup (main,
     slide, media, content, eyebrow, heading, desc, cta, nav, thumbs,
     thumb, progress).
   - property: the CSS property it feeds, written out.
   - modifier: --overlay (the overlay layout), --hover (state), --mobile
     (below 768px).
   Shared scales have no element: --gs-color-*, --gs-space-*, --gs-radius*.

   Two tiers. Element tokens default to the scales, so a palette or space
   change reaches everything that uses it; setting an element token changes
   only that element. Element tokens that default to a scale are not
   declared here, on purpose: a declared var() resolves at :root, and a
   scale override on a section further down would no longer reach them.
   Their defaults are listed in the comments and live in the var()
   fallbacks of the rules below.

   Declared on :where(:root), zero specificity: any theme rule outside a
   cascade layer wins, from :root or any ancestor, whatever the load order.
   Rules inside @layer lose to these unlayered defaults. Per-slider values
   (--gs-media-aspect-ratio, --gs-media-width) are set inline on .gslider.
   ============================================================ */
:where(:root) {
  /* ---- Scales -------------------------------------------------------- */

  /* Palette: wireframe greys, intentionally neutral. */
  --gs-color-text:         #1c1c1e;
  --gs-color-text-muted:   #5b5b62;
  --gs-color-text-subtle:  #6f6f77;   /* 4.5:1 on --gs-color-surface (the wireframe's #8a8a92 was 3.1:1) */
  --gs-color-accent:       #2f6fd0;   /* focus, active thumbnail, progress fill, button */
  --gs-color-on-accent:    #ffffff;   /* text on the accent */
  --gs-color-surface:      #f4f4f5;   /* the slide */
  --gs-color-surface-alt:  #e8e8ea;   /* image placeholders, progress track */
  /* --gs-color-focus: var(--gs-color-accent). Focus rings and the active
     thumbnail's ring; keep it 3:1 against what's behind. */

  /* Overlay layout: text over the image, on a dark gradient (the scrim). */
  --gs-color-text--overlay:        #ffffff;   /* also the overlay arrows, progress bar and focus rings */
  --gs-color-text-muted--overlay:  rgba(255, 255, 255, .86);
  --gs-color-scrim--overlay:       rgba(0, 0, 0, .72);   /* darkest point, at the bottom */

  /* Space, named as in Automatic.css. xs–l are fluid; see "Fluid sizes"
     below. These fixed values are the fallback for browsers without
     container units, and the sizes the fluid ones reach on a wide slider. */
  --gs-space-3xs: 0.5rem;
  --gs-space-2xs: 0.75rem;
  --gs-space-xs:  1rem;
  --gs-space-s:   1.5rem;
  --gs-space-m:   2rem;
  --gs-space-l:   3rem;

  /* Shape and motion */
  --gs-radius:     4px;
  --gs-radius-l:   6px;
  --gs-transition: 220ms cubic-bezier(.4, 0, .2, 1);

  /* ---- Element tokens -------------------------------------------------
     Keep text at 4.5:1 contrast against what's behind it. */

  /* Main panel, slide and image
     --gs-main-border-radius:  var(--gs-radius-l)
     --gs-slide-background:    var(--gs-color-surface)
     --gs-media-background:    var(--gs-color-surface-alt)   (behind the image: while it loads, and through a transparent one) */
  --gs-media-aspect-ratio: 16 / 9;   /* per slider: set inline on .gslider */
  --gs-media-width:        53.5%;    /* per slider: the split layout's image column; the arrow row aligns to it */

  /* Content, the text column
     --gs-content-padding:                       var(--gs-space-m)
     --gs-content-padding-block-start--overlay:  var(--gs-space-l)
     --gs-content-gap:                           var(--gs-space-2xs)   (between eyebrow, heading, description and button) */

  /* Eyebrow
     --gs-eyebrow-color:           var(--gs-color-text-subtle)
     --gs-eyebrow-color--overlay:  var(--gs-color-text-muted--overlay) */
  --gs-eyebrow-font-size:       0.75rem;
  --gs-eyebrow-letter-spacing:  0.12em;

  /* Heading. Uses the theme's heading font and letter-spacing (the plugin
     sets neither); to change the font in the slider only, target
     .gslider .gslider__heading.
     --gs-heading-color:           var(--gs-color-text)
     --gs-heading-color--overlay:  var(--gs-color-text--overlay) */
  --gs-heading-font-size:    clamp(1.6rem, 1.1rem + 2vw, 2.75rem);   /* fluid; see "Fluid sizes" below */
  --gs-heading-line-height:  1.12;

  /* Description
     --gs-desc-color:           var(--gs-color-text-muted)
     --gs-desc-color--overlay:  var(--gs-color-text-muted--overlay) */
  --gs-desc-font-size: 1em;   /* the slider's inherited size (theme p rules don't apply) */

  /* Button (.gslider__cta). All optional, resolved on the button; a
     framework bridge may supply values between the site's token and the
     default (see the hardening block).
     --gs-cta-color:                var(--gs-color-on-accent)
     --gs-cta-color--hover:         var(--gs-cta-color)
     --gs-cta-background:           var(--gs-color-accent)
     --gs-cta-background--hover:    var(--gs-cta-background)   (dimmed by --gs-cta-opacity--hover)
     --gs-cta-border-color:         var(--gs-cta-background)
     --gs-cta-border-color--hover:  var(--gs-cta-border-color), then the hover background
     --gs-cta-border-width:         0px
     --gs-cta-border-radius:        var(--gs-radius)
     --gs-cta-padding-block:        var(--gs-space-2xs)
     --gs-cta-padding-inline:       var(--gs-space-s)
     --gs-cta-font-size:            0.9375rem
     --gs-cta-font-weight:          600
     --gs-cta-line-height:          inherited
     --gs-cta-letter-spacing:       inherited
     --gs-cta-text-transform:       inherited
     --gs-cta-opacity--hover:       0.88 (1 on an Automatic.css button; set 1
                                    when you give the hover its own colours)
     --gs-cta-margin-block-start:   var(--gs-space-3xs)   (on top of the content gap) */

  /* Arrows (.gslider__nav). The colours are the split layout's; the overlay
     layout's arrows follow --gs-color-text--overlay.
     --gs-nav-icon:                 none: Swiper's chevron   (SVG code on the Appearance screen, printed as url(data:…))
     --gs-nav-color:                var(--gs-color-text)   (the icon)
     --gs-nav-color--hover:         var(--gs-nav-color)
     --gs-nav-background--hover:    var(--gs-color-surface)
     --gs-nav-border-color--hover:  var(--gs-nav-border-color)
     --gs-nav-gap:                  var(--gs-space-2xs) */
  --gs-nav-size:               44px;
  --gs-nav-icon-size:          15px;  /* the chevron's height, or the box a custom icon fits in */
  --gs-nav-text-stroke-width:  0px;   /* thickens the chevron: a stroke in its own colour */
  --gs-nav-background:         #ffffff;
  --gs-nav-border-color:       #d2d2d6;
  --gs-nav-border-width:       1px;

  /* Full-bleed layout (Layout "Split, full bleed"): the site's content
     container the text lines up with.
     --gs-container-padding:  var(--gs-space-m)   (the least gap between the text and the window's edge) */
  --gs-container-width:  1200px;

  /* Thumbnail strip (.gslider__thumbs) and thumbnails
     --gs-thumbs-margin-block-start:  var(--gs-space-xs)
     --gs-thumb-border-radius:        var(--gs-radius)
     Thumbnails "In a notch" (.gslider__dock):
     --gs-notch-padding:              var(--gs-space-3xs)   (between the notch's edge and the strip)
     --gs-notch-radius:               unset: round ends, concentric with the arrows */
  --gs-thumbs-gap:               12px;   /* ≥768px; px only (read by the JS) */
  --gs-thumbs-gap--mobile:       8px;    /* <768px; px only */
  --gs-thumbs-per-row--mobile:   5;      /* <768px: thumbnails size so this many fit across */
  --gs-thumbs-fade:              24px;   /* edge fade when the strip has more thumbnails off-screen; px only */
  --gs-thumb-width:              104px;
  --gs-thumb-min-width--mobile:  44px;   /* <768px: never narrower than this (tap target) */
  --gs-thumb-aspect-ratio:       16 / 9;

  /* Progress bar
     --gs-progress-color:                var(--gs-color-accent)          (the fill)
     --gs-progress-color--overlay:       var(--gs-color-text--overlay)
     --gs-progress-background:           var(--gs-color-surface-alt)     (the track)
     --gs-progress-background--overlay:  --gs-color-text--overlay at 28% */
  --gs-progress-height: 3px;

  /* Entrance */
  --gs-entrance-offset:         24px;
  --gs-entrance-duration:       950ms;   /* travel time */
  --gs-entrance-delay:          160ms;   /* pause after the trigger before anything moves */
  --gs-entrance-easing:         cubic-bezier(.16, .84, .44, 1);
  --gs-thumbs-entrance-delay:   360ms;   /* extra delay on the thumbnail strip */
  --gs-thumb-entrance-stagger:  100ms;   /* gap between each thumbnail */
}

/* Fluid sizes, Automatic.css-style clamp()s, but measured against the
   slider's own width (cqi: 1% of the .gslider container) rather than the
   viewport, so a slider in a narrow column gets narrow-slider spacing on a
   wide screen. Each spacing step ramps from its smaller size on a
   360px-wide slider (22.5rem) to the fixed size above on a 1200px-wide
   one; the heading ramps from 1.6rem at about 350px to 2.75rem at about
   1150px (without container units it keeps the viewport-based clamp
   above). Override any of them with a fixed value, or your framework's
   own variables (e.g. --gs-space-m: var(--space-m)). Sliders → Appearance
   writes the same kind of clamp from a min and a max. */
@supports (width: 1cqi) {
  :where(:root) {
    --gs-heading-font-size: clamp(1.6rem, 1.1rem + 2.3cqi, 2.75rem);
    --gs-space-xs: clamp(0.75rem, 0.75rem + (100cqi - 22.5rem) / 210, 1rem);    /* 12 → 16px */
    --gs-space-s: clamp(1.25rem, 1.25rem + (100cqi - 22.5rem) / 210, 1.5rem);  /* 20 → 24px */
    --gs-space-m: clamp(1.5rem, 1.5rem + (100cqi - 22.5rem) / 105, 2rem);      /* 24 → 32px */
    --gs-space-l: clamp(2.25rem, 2.25rem + (100cqi - 22.5rem) / 70, 3rem);     /* 36 → 48px */
  }
}
/* Without container units, phones use the smaller slide padding. */
@supports not (width: 1cqi) {
  @media (max-width: 767px) {
    :where(:root) { --gs-space-m: 1.5rem; }
  }
}

/* ============================================================
   COMPONENT: .gslider
   BEM-ish, prefixed, no dependency on page chrome.
   ============================================================ */

/* Border-box inside the component only (the wireframe set this page-wide).
   :where() keeps specificity at zero, as the wireframe's universal selector
   was, so Swiper's own .swiper-wrapper box-sizing still wins. */
:where(.gslider), :where(.gslider) *, :where(.gslider) *::before, :where(.gslider) *::after { box-sizing: border-box; }
/* A defined block box whatever the host does to <section> or its parent:
   as a flex item, Swiper would measure its own runaway width (e.g. ACSS's
   section{display:flex}, Gutenberg Row blocks). */
.gslider { position: relative; display: block; inline-size: 100%; min-inline-size: 0; padding: 0; gap: 0; }
/* The container the fluid sizes measure. Inline-size containment means the
   slider's width comes from its parent, never its content, which is what a
   Swiper root needs anyway (a content-sized parent used to give it a
   runaway width). The flip side: a parent that sizes to its content gives
   the slider no width at all. That includes a grid with justify-content or
   place-content start/center/end, fit-content() / max-content / auto tracks,
   and inline-block, float, absolute or width:fit-content parents without a
   width. Give such a parent a width (width:100%, flex:1, "Fill"). */
.gslider { container: gslider / inline-size; }

/* ---- Main slider ---------------------------------------- */
.gslider__main {
  overflow: hidden;
  overflow: clip;         /* not programmatically scrollable: find-in-page and #fragments can't shift hidden slides into view */
  border-radius: var(--gs-main-border-radius, var(--gs-radius-l));
}

.gslider__slide {
  display: grid;
  background: var(--gs-slide-background, var(--gs-color-surface));
  color: var(--gs-color-text); /* the wireframe got this from body; a host's text colour must not land on the light slide */
  block-size: auto;       /* let Swiper measure content, not collapse it */
}
/* Beats host heading colours (e.g. a builder row's "h2 { color }"); the
   overlay rule below still wins by source order. */
.gslider .gslider__slide .gslider__heading { color: var(--gs-heading-color, var(--gs-color-text)); }

/* Layout A — Split: media beside content (default).
   Placement is explicit, so the image's side is visual only: the template
   puts the text first (screen readers meet it before the image), and a
   copied template with the image first lays out the same. Phones: the
   image on top. */
.gslider[data-layout="split"] .gslider__slide {
  grid-template-columns: 1fr;
}
.gslider[data-layout="split"] .gslider__media { grid-row: 1; grid-column: 1; }
.gslider[data-layout="split"] .gslider__content { grid-row: 2; grid-column: 1; }
@media (min-width: 768px) {
  .gslider[data-layout="split"] .gslider__slide { grid-template-columns: var(--gs-media-width) 1fr; }
  .gslider[data-layout="split"] .gslider__content { grid-row: 1; grid-column: 2; }
  /* Image side "Right": data-media-side="end" (logical, so RTL mirrors it). */
  .gslider[data-layout="split"][data-media-side="end"] .gslider__slide { grid-template-columns: 1fr var(--gs-media-width); }
  .gslider[data-layout="split"][data-media-side="end"] .gslider__media { grid-column: 2; }
  .gslider[data-layout="split"][data-media-side="end"] .gslider__content { grid-column: 1; }
}

/* Layout B — Overlay: content layered over media.
   Explicit 1x1 placement rather than named areas: both children are
   pinned to row 1 / column 1, so they occupy the same cell no matter
   what the cascade does elsewhere. */
.gslider[data-layout="overlay"] .gslider__slide {
  grid-template-columns: 1fr;
  grid-template-rows: auto;
}
.gslider[data-layout="overlay"] .gslider__media,
.gslider[data-layout="overlay"] .gslider__content {
  grid-column: 1 / -1;
  grid-row: 1 / -1;
  min-inline-size: 0;
  min-block-size: 0;
}
.gslider[data-layout="overlay"] .gslider__media { z-index: 1; }
.gslider[data-layout="overlay"] .gslider__content {
  z-index: 2;
  align-self: end;
  justify-content: flex-end;
  background: linear-gradient(to top, var(--gs-color-scrim--overlay) 12%, transparent 82%);
  color: var(--gs-color-text--overlay);
  padding-block:
    var(--gs-content-padding-block-start--overlay, var(--gs-space-l))
    calc(var(--gs-content-padding, var(--gs-space-m)) + var(--gs-nav-size) + var(--gs-space-xs));
  padding-inline: var(--gs-content-padding, var(--gs-space-m));
}
@media (min-width: 768px) {
  .gslider[data-layout="overlay"] .gslider__heading { max-inline-size: 20ch; }
}
.gslider[data-layout="overlay"] .gslider__eyebrow { color: var(--gs-eyebrow-color--overlay, var(--gs-color-text-muted--overlay)); }
.gslider[data-layout="overlay"] .gslider__desc { color: var(--gs-desc-color--overlay, var(--gs-color-text-muted--overlay)); }
.gslider[data-layout="overlay"] .gslider__heading { color: var(--gs-heading-color--overlay, var(--gs-color-text--overlay)); }

/* Media block.
   The ::before spacer establishes a MINIMUM height from the chosen
   ratio (so short copy still gets a well-proportioned image and no
   layout shift), while the absolutely-positioned img fills whatever
   height the grid row ends up being. Result: the image always reaches
   the bottom of the slide, and the ratio is a floor, not a ceiling. */
.gslider__media {
  position: relative;
  background: var(--gs-media-background, var(--gs-color-surface-alt));   /* transparent: the slide background shows through */
  overflow: hidden;
}
.gslider__media::before {
  content: "";
  display: block;
  inline-size: 100%;
  aspect-ratio: var(--gs-media-aspect-ratio);
  max-block-size: var(--gs-media-max-height, none);   /* caps the floor, not the slide: longer text still grows it */
}
.gslider__media img {
  position: absolute;
  inset: 0;
  inline-size: 100%; block-size: 100%;
  object-fit: cover;
  display: block;
}
/* A slide's video: over the image, with the same size and crop. It fades in
   once it's actually playing (data-gs-playing, set by the script), so the
   image shows while it loads and stays when it can't play. Phones get the
   image only; the script doesn't load the video there. */
.gslider__media .gslider__video {
  position: absolute;
  inset: 0;
  inline-size: 100%; block-size: 100%;
  max-inline-size: none;   /* themes' "video { max-width: 100%; height: auto }" */
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity 400ms ease;
}
.gslider__media .gslider__video[data-gs-playing] { opacity: 1; }
@media (max-width: 767px) {
  .gslider__media .gslider__video { display: none; }
}

/* Content block */
.gslider__content {
  display: flex; flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--gs-content-gap, var(--gs-space-2xs));
  padding: var(--gs-content-padding, var(--gs-space-m));
  /* Reserve room so the nav row never collides with the CTA */
  padding-block-end: calc(var(--gs-content-padding, var(--gs-space-m)) + var(--gs-nav-size) + var(--gs-space-xs));
}
/* A single slide renders no arrow row (after the overlay rule on purpose). */
.gslider:not(:has(.gslider__nav-row)) .gslider__content { padding-block-end: var(--gs-content-padding, var(--gs-space-m)); }

/* Margin, size, colour and spacing of the text and the button are set in
   the host-theme hardening block below, at a specificity themes and
   framework classes don't reach. */
.gslider__eyebrow {
  /* The template puts the eyebrow after the heading, so screen readers
     (and heading navigation) meet the heading first; order shows it above. */
  order: -1;
  text-transform: uppercase;
  letter-spacing: var(--gs-eyebrow-letter-spacing);
}
.gslider__heading { text-wrap: balance; }
.gslider__desc { max-inline-size: 46ch; }
/* Footnote markers don't open up the line they're on. */
.gslider__desc :is(sup, sub) { line-height: 0; }
.gslider__cta { margin-block-start: var(--gs-cta-margin-block-start, var(--gs-space-3xs)); }

/* ---- Thumbnail strip ------------------------------------ */
/* Sits below the main slider, horizontally centered.
   Doubles as the slide indicator AND the slide navigation. */
.gslider__thumbs {
  margin-block-start: var(--gs-thumbs-margin-block-start, var(--gs-space-xs));
  /* Room for the active thumb's 2px outline + 2px offset at the strip's
     edges; the strip clips overflow, so without it the ring is cut off when
     the strip has scrolled to an end (phones). */
  padding: 4px;  /* the ring's reach: 2px outline + 2px offset */
}
.gslider__thumbs .swiper-slide {
  inline-size: var(--gs-thumb-width);    /* fixed width + slidesPerView:'auto' */
  block-size: auto;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity var(--gs-transition);
}
@media (hover: hover) {
  .gslider__thumbs .swiper-slide:hover { opacity: 0.8; }
}

/* Phones: size thumbs so --gs-thumbs-per-row--mobile fit across the strip. With
   more slides than that, the strip scrolls (see the fades below). */
@media (max-width: 767px) {
  .gslider__thumbs .swiper-slide {
    inline-size: max(
      var(--gs-thumb-min-width--mobile),
      calc((100% - (var(--gs-thumbs-per-row--mobile) - 1) * var(--gs-thumbs-gap--mobile)) / var(--gs-thumbs-per-row--mobile))
    );
  }
}

/* More thumbs than fit: fade the edge(s) with hidden thumbs. The script sets
   the --more-start / --more-end modifiers from Swiper's position, and
   neither when the strip fits (it's then centred and locked). Gradients
   have no logical direction keywords, so the RTL rules below flip them. */
.gslider__thumbs.gslider__thumbs--more-start.gslider__thumbs--more-end {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--gs-thumbs-fade), #000 calc(100% - var(--gs-thumbs-fade)), transparent);
          mask-image: linear-gradient(to right, transparent, #000 var(--gs-thumbs-fade), #000 calc(100% - var(--gs-thumbs-fade)), transparent);
}
.gslider__thumbs.gslider__thumbs--more-start:not(.gslider__thumbs--more-end) {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--gs-thumbs-fade));
          mask-image: linear-gradient(to right, transparent, #000 var(--gs-thumbs-fade));
}
.gslider__thumbs.gslider__thumbs--more-end:not(.gslider__thumbs--more-start) {
  -webkit-mask-image: linear-gradient(to left, transparent, #000 var(--gs-thumbs-fade));
          mask-image: linear-gradient(to left, transparent, #000 var(--gs-thumbs-fade));
}
:where([dir="rtl"]) .gslider__thumbs.gslider__thumbs--more-start:not(.gslider__thumbs--more-end) {
  -webkit-mask-image: linear-gradient(to left, transparent, #000 var(--gs-thumbs-fade));
          mask-image: linear-gradient(to left, transparent, #000 var(--gs-thumbs-fade));
}
:where([dir="rtl"]) .gslider__thumbs.gslider__thumbs--more-end:not(.gslider__thumbs--more-start) {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--gs-thumbs-fade));
          mask-image: linear-gradient(to right, transparent, #000 var(--gs-thumbs-fade));
}

.gslider__thumb-inner {
  position: relative;
  aspect-ratio: var(--gs-thumb-aspect-ratio);
  background: var(--gs-color-surface-alt);
  border-radius: var(--gs-thumb-border-radius, var(--gs-radius));
  overflow: hidden;
  outline: 2px solid transparent;
  outline-offset: 2px;
  transition: outline-color var(--gs-transition);
}
.gslider__thumb-inner img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }

/* Active state — this is the "current slide indicator" the brief asks for. */
.gslider__thumbs .swiper-slide-thumb-active { opacity: 1; }
.gslider__thumbs .swiper-slide-thumb-active .gslider__thumb-inner {
  outline-color: var(--gs-color-focus, var(--gs-color-accent));
}

/* ---- Progress meter -------------------------------------
   Hairline bar along the very top of the slider. Uses Swiper's
   own fill element rather than Swiper's pagination module, so one bar
   can serve both the autoplay timer and the position indicator
   and works alongside the thumbs module without conflict. */
.gslider__progress {
  position: absolute;
  inset-block-start: 0; inset-inline-start: 0;
  z-index: 6;
  inline-size: 100%;
  block-size: var(--gs-progress-height);
  background: var(--gs-progress-background, var(--gs-color-surface-alt));
  overflow: hidden;
}
.gslider__progress-fill {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  background: var(--gs-progress-color, var(--gs-color-accent));
  transform: scaleX(0);
  transform-origin: left center;  /* no logical keyword; flipped for RTL at the end */
  will-change: transform;
}

/* Position mode (autoplay off): eased step on each slide change. */
.gslider__progress-fill { transition: transform 400ms cubic-bezier(.4, 0, .2, 1); }

/* Timer mode (autoplay on): driven frame-by-frame, so no transition —
   a transition here would lag behind the countdown and stutter. */
.gslider[data-gs-progress-mode="timer"] .gslider__progress-fill { transition: none; }

.gslider[data-layout="overlay"] .gslider__progress { background: var(--gs-progress-background--overlay, rgba(255,255,255,.28)); }
.gslider[data-layout="overlay"] .gslider__progress-fill { background: var(--gs-progress-color--overlay, var(--gs-color-text--overlay)); }

/* ---- Arrows ---------------------------------------------
   Sit in a row pinned to the bottom of the CONTENT column:
   prev aligns under the CTA, next pushes to the far corner.
   The row lives outside .swiper-wrapper (one set of controls,
   not one per slide) but is positioned over the content area. */
.gslider__nav-row {
  position: absolute;
  z-index: 5;
  inset-block-end: 0; inset-inline: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--gs-nav-gap, var(--gs-space-2xs));
  padding: var(--gs-content-padding, var(--gs-space-m));   /* matches .gslider__content, so prev sits under the CTA */
  pointer-events: none;          /* row is a layout shell; buttons re-enable */
}
@media (min-width: 768px) {
  /* Split layout: confine the row to the text column */
  .gslider[data-layout="split"] .gslider__nav-row { inset-inline-start: var(--gs-media-width); }
  .gslider[data-layout="split"][data-media-side="end"] .gslider__nav-row { inset-inline: 0 var(--gs-media-width); }
}

.gslider__nav {
  position: static;              /* override Swiper's absolute defaults */
  pointer-events: auto;
  display: grid; place-items: center;
  flex: 0 0 auto;
  inline-size: var(--gs-nav-size); block-size: var(--gs-nav-size);
  margin: 0;
  border-radius: 50%;
  transition: background var(--gs-transition), color var(--gs-transition), border-color var(--gs-transition), opacity var(--gs-transition);
  /* colours: host-theme hardening block */
}
.gslider__nav::after { font-size: var(--gs-nav-icon-size); font-weight: 700; -webkit-text-stroke-width: var(--gs-nav-text-stroke-width); }
/* A custom arrow icon (--gs-nav-icon): the SVG as a mask over the icon
   colour, on ::before, in the same grid cell as the chevron. Unset, the
   mask is a transparent gradient and ::before shows nothing. Set, the
   Appearance output also sets --_gs-nav-glyph: transparent, which hides
   the chevron (and its stroke). The icon points to the next slide; the
   previous arrow mirrors it, and in RTL the next one does (Swiper swaps
   its own chevrons the same way). */
.gslider__nav::before,
.gslider__nav::after { grid-area: 1 / 1; }
.gslider__nav::before {
  content: "";
  inline-size: var(--gs-nav-icon-size);
  block-size: var(--gs-nav-icon-size);
  background-color: currentColor;
  -webkit-mask: var(--gs-nav-icon, linear-gradient(transparent, transparent)) center / contain no-repeat;
  mask: var(--gs-nav-icon, linear-gradient(transparent, transparent)) center / contain no-repeat;
}
.gslider .gslider__nav::after { color: var(--_gs-nav-glyph, currentColor); }
.gslider__nav.swiper-button-prev::before { transform: scaleX(-1); }
:where([dir="rtl"]) .gslider__nav.swiper-button-prev::before { transform: none; }
:where([dir="rtl"]) .gslider__nav.swiper-button-next::before { transform: scaleX(-1); }
.gslider__nav.swiper-button-disabled { opacity: 0.35; pointer-events: none; }
.gslider__nav.swiper-button-lock { display: none; }

/* Pause / play: one button for the slider's motion, its autoplay and any
   video. An arrow-style button (it shares .gslider__nav, so the arrow
   tokens style it) after the next arrow, with its own icon: two bars, a
   triangle once paused (data-gs-paused on the root). Printed hidden; the
   script shows it when something can move. In a row of arrows, next moves
   over to sit beside it. */
.gslider__nav.gslider__pause[hidden] { display: none; }
.gslider .gslider__pause::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect x='3' y='1.5' width='3.5' height='13' rx='1'/%3E%3Crect x='9.5' y='1.5' width='3.5' height='13' rx='1'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect x='3' y='1.5' width='3.5' height='13' rx='1'/%3E%3Crect x='9.5' y='1.5' width='3.5' height='13' rx='1'/%3E%3C/svg%3E");
}
.gslider[data-gs-paused] .gslider__pause::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 2.2v11.6a1 1 0 0 0 1.5.86l9.2-5.8a1 1 0 0 0 0-1.72L5.5 1.34A1 1 0 0 0 4 2.2z'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 2.2v11.6a1 1 0 0 0 1.5.86l9.2-5.8a1 1 0 0 0 0-1.72L5.5 1.34A1 1 0 0 0 4 2.2z'/%3E%3C/svg%3E");
}
.gslider__nav-row:has(> .gslider__pause:not([hidden])) > .swiper-button-next { margin-inline-start: auto; }

/* Overlay layout puts the row on dark artwork — invert the buttons. Only
   the arrows over the slide: in a notch (.gslider__dock) they sit on the
   page and keep the regular colours. :where() keeps the specificity. */
.gslider[data-layout="overlay"] :where(.gslider__main) .gslider__nav {
  background: rgba(255,255,255,.14);
  border-color: rgba(255,255,255,.4);
  color: var(--gs-color-text--overlay);
  backdrop-filter: blur(6px);
}
@media (hover: hover) {
  .gslider[data-layout="overlay"] :where(.gslider__main) .gslider__nav:hover { background: rgba(255,255,255,.26); }
}
/* Derive the overlay controls from --gs-color-text--overlay, so dark overlay
   text (for light artwork) recolours them too. Inside @supports rather than as a
   second declaration: a var() value can't fall back at parse time. */
@supports (color: color-mix(in srgb, red 50%, transparent)) {
  .gslider[data-layout="overlay"] :where(.gslider__main) .gslider__nav {
    background: color-mix(in srgb, var(--gs-color-text--overlay) 14%, transparent);
    border-color: color-mix(in srgb, var(--gs-color-text--overlay) 40%, transparent);
  }
  @media (hover: hover) {
    .gslider[data-layout="overlay"] :where(.gslider__main) .gslider__nav:hover { background: color-mix(in srgb, var(--gs-color-text--overlay) 26%, transparent); }
  }
  .gslider[data-layout="overlay"] .gslider__progress { background: var(--gs-progress-background--overlay, color-mix(in srgb, var(--gs-color-text--overlay) 28%, transparent)); }
}
/* The accent focus ring is too faint on the dark scrim; use the overlay text colour. */
.gslider[data-layout="overlay"] .gslider__main :is(a, button):focus-visible { outline-color: var(--gs-color-text--overlay); }

/* ---- Layout A2 — Split, full bleed ------------------------
   data-width="bleed" on a split slider. Meant for a full-width row: the
   image runs from the split point to the window's edge, and the text lines
   up with the site's content container (--gs-container-width). The gutter
   beside the container is the slider's own width (100cqi: no 100vw, so no
   scrollbar overflow) less the container, halved, and at least
   --gs-container-padding. Each slide pads by it, so its grid (the split
   rules above) divides the container; the image steps out into the gutter
   on its side. Declared here, used only by descendants, so 100cqi is the
   slider's width. */
.gslider[data-width="bleed"] {
  --_gs-gutter: max(var(--gs-container-padding, var(--gs-space-m)), (100vw - var(--gs-container-width)) / 2);
}
@supports (width: 1cqi) {
  .gslider[data-width="bleed"] { --_gs-gutter: max(var(--gs-container-padding, var(--gs-space-m)), (100cqi - var(--gs-container-width)) / 2); }
}
.gslider[data-width="bleed"] .gslider__main { border-radius: 0; }
.gslider[data-width="bleed"] .gslider__slide { padding-inline: var(--_gs-gutter); }
/* Phones: the image edge to edge, the text and arrows inside the container padding. */
.gslider[data-width="bleed"] .gslider__media { margin-inline: calc(-1 * var(--_gs-gutter)); }
.gslider[data-width="bleed"] .gslider__content { padding-inline: 0; }
.gslider[data-width="bleed"] .gslider__nav-row { padding-inline: var(--_gs-gutter); }
.gslider[data-width="bleed"] .gslider__thumbs { margin-inline: var(--_gs-gutter); }
@media (min-width: 768px) {
  /* The image reaches the window's edge on its side. The text's outer edge
     is the container's; its padding toward the image stays. */
  .gslider[data-width="bleed"] .gslider__media { margin-inline: calc(-1 * var(--_gs-gutter)) 0; }
  .gslider[data-width="bleed"] .gslider__content { padding-inline: var(--gs-content-padding, var(--gs-space-m)) 0; }
  .gslider[data-width="bleed"][data-media-side="end"] .gslider__media { margin-inline: 0 calc(-1 * var(--_gs-gutter)); }
  .gslider[data-width="bleed"][data-media-side="end"] .gslider__content { padding-inline: 0 var(--gs-content-padding, var(--gs-space-m)); }
  /* Anchored at the edge that meets the text: a wider window shows more
     of the far side. object-position has no logical keywords (RTL below). */
  .gslider[data-width="bleed"] .gslider__media img { object-position: 100% 50%; }
  .gslider[data-width="bleed"][data-media-side="end"] .gslider__media img { object-position: 0% 50%; }
  :where([dir="rtl"]) .gslider[data-width="bleed"] .gslider__media img { object-position: 0% 50%; }
  :where([dir="rtl"]) .gslider[data-width="bleed"][data-media-side="end"] .gslider__media img { object-position: 100% 50%; }
  .gslider[data-width="bleed"] .gslider__media .gslider__video { object-position: 100% 50%; }
  .gslider[data-width="bleed"][data-media-side="end"] .gslider__media .gslider__video { object-position: 0% 50%; }
  :where([dir="rtl"]) .gslider[data-width="bleed"] .gslider__media .gslider__video { object-position: 0% 50%; }
  :where([dir="rtl"]) .gslider[data-width="bleed"][data-media-side="end"] .gslider__media .gslider__video { object-position: 100% 50%; }
  /* Arrows: the slide's gutter and columns, both buttons in the text column
     (prev under the button, next at the container's edge). */
  .gslider[data-layout="split"][data-width="bleed"] .gslider__nav-row {
    inset-inline: 0;
    display: grid;
    grid-template-columns: var(--gs-media-width) 1fr;
    column-gap: 0;   /* the row's gap is for its flex layout; here it would shift the text column */
  }
  .gslider[data-layout="split"][data-width="bleed"][data-media-side="end"] .gslider__nav-row { grid-template-columns: 1fr var(--gs-media-width); }
  .gslider[data-width="bleed"] .gslider__nav-row .gslider__nav { grid-row: 1; grid-column: 2; }
  .gslider[data-width="bleed"][data-media-side="end"] .gslider__nav-row .gslider__nav { grid-column: 1; }
  .gslider[data-width="bleed"] .gslider__nav-row .swiper-button-prev { justify-self: start; margin-inline-start: var(--gs-content-padding, var(--gs-space-m)); }
  .gslider[data-width="bleed"] .gslider__nav-row .swiper-button-next { justify-self: end; }
  .gslider[data-width="bleed"][data-media-side="end"] .gslider__nav-row .swiper-button-prev { margin-inline-start: 0; }
  .gslider[data-width="bleed"][data-media-side="end"] .gslider__nav-row .swiper-button-next { margin-inline-end: var(--gs-content-padding, var(--gs-space-m)); }
  /* The pause button takes next's place at the end, and next moves in beside it. */
  .gslider[data-width="bleed"] .gslider__nav-row .gslider__pause { justify-self: end; }
  .gslider[data-width="bleed"][data-media-side="end"] .gslider__nav-row .gslider__pause { margin-inline-end: var(--gs-content-padding, var(--gs-space-m)); }
  .gslider[data-width="bleed"] .gslider__nav-row:has(> .gslider__pause:not([hidden])) > .swiper-button-next {
    margin-inline-end: calc(var(--gs-nav-size) + var(--gs-nav-gap, var(--gs-space-2xs)));
  }
  .gslider[data-width="bleed"][data-media-side="end"] .gslider__nav-row:has(> .gslider__pause:not([hidden])) > .swiper-button-next {
    margin-inline-end: calc(var(--gs-content-padding, var(--gs-space-m)) + var(--gs-nav-size) + var(--gs-nav-gap, var(--gs-space-2xs)));
  }
}

/* ---- Thumbnails in a notch, or none ----------------------
   data-thumbs="notch": the template puts the arrows and the strip in
   .gslider__dock after the slides (previous, strip, next, then the pause
   button when there is one). From 768px the
   row is centred on the slide area's bottom edge, and a mask on the slide
   area cuts a notch around it: the top half of a pill, whose rounded
   corners are concentric with the arrows. It's a real cut, so whatever is
   behind the slider shows through; nothing has to match the page.
   The notch is worked out here, not measured. Its width is the row's
   natural width (the slide count, --_gs-thumbs-count from the template,
   times the thumbnail width, plus the gaps and the arrows), up to the
   container; its depth is half the row's height plus --gs-notch-padding.
   The mask and the row use the same values, so they always match. On
   phones there's no notch: the arrows and the strip form one row below
   the slide. Every rule needs the dock, so a template copied before 0.19
   (no dock) shows the strip below. */
.gslider[data-thumbs="notch"]:has(> .gslider__dock) {
  --_gs-notch-pad:    var(--gs-notch-padding, var(--gs-space-3xs));
  --_gs-dock-gap:     var(--gs-nav-gap, var(--gs-space-2xs));
  --_gs-strip-block:  calc(var(--gs-thumb-width) / (var(--gs-thumb-aspect-ratio)) + 8px);   /* the strip's 4px padding, twice */
  --_gs-dock-block:   max(var(--gs-nav-size), var(--_gs-strip-block));
  --_gs-notch-depth:  calc(var(--_gs-dock-block) / 2 + var(--_gs-notch-pad));
  --_gs-notch-radius: min(var(--gs-notch-radius, 9999px), var(--_gs-notch-depth));
  /* Room at each end so an arrow's centre is a corner's centre. */
  --_gs-dock-pad:     max(var(--_gs-notch-pad), var(--_gs-notch-radius) - var(--gs-nav-size) / 2);
  --_gs-dock-edge:    var(--gs-content-padding, var(--gs-space-m));
  --_gs-dock-buttons: 2;   /* the arrows; 3 with the pause button */
  /* 1px of slack: Swiper counts a strip as fitting only with room to spare. */
  --_gs-notch-width:  min(
    100% - 2 * var(--_gs-dock-edge),
    2 * var(--_gs-dock-pad) + var(--_gs-dock-buttons) * (var(--gs-nav-size) + var(--_gs-dock-gap))
      + var(--_gs-thumbs-count) * var(--gs-thumb-width) + (var(--_gs-thumbs-count) - 1) * var(--gs-thumbs-gap) + 9px
  );
}
.gslider[data-thumbs="notch"]:has(> .gslider__dock > .gslider__pause:not([hidden])) { --_gs-dock-buttons: 3; }
.gslider[data-thumbs="notch"][data-width="bleed"]:has(> .gslider__dock) { --_gs-dock-edge: var(--_gs-gutter); }

.gslider__dock {
  display: flex;
  align-items: center;
  gap: var(--gs-nav-gap, var(--gs-space-2xs));
  margin-block-start: var(--gs-thumbs-margin-block-start, var(--gs-space-xs));
}
.gslider[data-width="bleed"] .gslider__dock { margin-inline: var(--_gs-gutter); }
.gslider .gslider__dock .gslider__thumbs { flex: 1 1 0; min-inline-size: 0; margin: 0; }

@media (min-width: 768px) {
  /* The slide area, less the notch: what's above it, what's either side,
     and the two corners (each a square beside the notch, with a quarter
     circle cut from its bottom corner). The corner layers reach 2px above
     the notch, so no seam shows where they meet the layer above. */
  .gslider[data-thumbs="notch"]:has(> .gslider__dock) .gslider__main {
    --_gs-notch-side: calc(50% - var(--_gs-notch-width) / 2);
    --_gs-notch-mask:
      linear-gradient(#000 0 0) top / 100% calc(100% - var(--_gs-notch-depth)) no-repeat,
      linear-gradient(#000 0 0) left / var(--_gs-notch-side) 100% no-repeat,
      linear-gradient(#000 0 0) right / var(--_gs-notch-side) 100% no-repeat,
      radial-gradient(circle at 100% 100%, transparent calc(var(--_gs-notch-radius) - .5px), #000 calc(var(--_gs-notch-radius) + .5px))
        left 0 bottom calc(var(--_gs-notch-depth) - var(--_gs-notch-radius)) / calc(var(--_gs-notch-side) + var(--_gs-notch-radius)) calc(var(--_gs-notch-radius) + 2px) no-repeat,
      radial-gradient(circle at 0 100%, transparent calc(var(--_gs-notch-radius) - .5px), #000 calc(var(--_gs-notch-radius) + .5px))
        right 0 bottom calc(var(--_gs-notch-depth) - var(--_gs-notch-radius)) / calc(var(--_gs-notch-side) + var(--_gs-notch-radius)) calc(var(--_gs-notch-radius) + 2px) no-repeat;
    -webkit-mask: var(--_gs-notch-mask);
            mask: var(--_gs-notch-mask);
  }
  /* The row: centred on the edge, as wide as the notch. Above the slide
     area (Swiper gives that z-index 1), which a mask doesn't stop from
     taking clicks. */
  .gslider[data-thumbs="notch"]:has(> .gslider__dock) .gslider__dock {
    position: relative;
    z-index: 2;
    box-sizing: border-box;
    inline-size: var(--_gs-notch-width);
    block-size: calc(2 * var(--_gs-notch-depth));
    margin-block-start: calc(-1 * var(--_gs-notch-depth));
    margin-inline: auto;
    padding: var(--_gs-notch-pad) var(--_gs-dock-pad);
  }
  /* The text keeps clear of the notch (in place of the arrow row's allowance). */
  .gslider[data-thumbs="notch"]:has(> .gslider__dock) .gslider__content {
    padding-block-end: calc(var(--gs-content-padding, var(--gs-space-m)) + var(--_gs-notch-depth));
  }
}

/* data-thumbs="none": the template prints no strip. This hides the one a
   template copied before 0.19 prints (the script leaves it alone). */
.gslider[data-thumbs="none"] .gslider__thumbs { display: none; }

/* ---- Scroll-triggered entrance --------------------------
   The data-gs-entrance attribute is set by JS, so if JS fails or is
   blocked the slider simply renders visible — nothing is hidden by
   CSS alone. Two staged pieces: the slider body, then the thumb
   strip a beat later. */
.gslider[data-gs-entrance] .gslider__main {
  transition: opacity var(--gs-entrance-duration) var(--gs-entrance-easing),
              transform var(--gs-entrance-duration) var(--gs-entrance-easing);
  transition-delay: var(--gs-entrance-delay);
}
.gslider[data-gs-entrance="pending"] .gslider__main {
  opacity: 0;
  transform: translateY(var(--gs-entrance-offset));
}
.gslider[data-gs-entrance="in"] .gslider__main {
  opacity: 1;
  transform: none;
}

/* Thumbnails rise one after another. A keyframe animation is used
   here rather than a transition so it doesn't clobber the inner
   element's outline transition (the active-thumb highlight must
   stay instant). --gs-i is stamped on each thumb by JS, so the stagger
   works for any number of slides the CMS loop emits. */
@keyframes gslider-thumb-in {
  from { opacity: 0; transform: translateY(var(--gs-entrance-offset)); }
  to   { opacity: 1; transform: none; }
}
.gslider[data-gs-entrance="pending"] .gslider__thumb-inner { opacity: 0; }
.gslider[data-gs-entrance="in"] .gslider__thumb-inner {
  animation: gslider-thumb-in var(--gs-entrance-duration) var(--gs-entrance-easing) both;
  animation-delay: calc(
    var(--gs-entrance-delay) + var(--gs-thumbs-entrance-delay) + (var(--gs-i, 0) * var(--gs-thumb-entrance-stagger))
  );
}

/* Arrows in a notch rise with the strip. Only a "from" keyframe, and no
   fill afterwards, so they end on their own opacity (a disabled arrow's
   is lower). Hidden until then by visibility, not opacity: the arrows'
   opacity transition would run when "pending" goes, and a transition
   outranks the animation, so they'd flash. */
@keyframes gslider-dock-nav-in {
  from { opacity: 0; transform: translateY(var(--gs-entrance-offset)); }
}
.gslider[data-gs-entrance="pending"] .gslider__dock .gslider__nav { visibility: hidden; }
.gslider[data-gs-entrance="in"] .gslider__dock .gslider__nav {
  animation: gslider-dock-nav-in var(--gs-entrance-duration) var(--gs-entrance-easing) backwards;
  animation-delay: calc(var(--gs-entrance-delay) + var(--gs-thumbs-entrance-delay));
}

/* Never hide content from anyone who has asked for less motion. */
@media (prefers-reduced-motion: reduce) {
  .gslider[data-gs-entrance="pending"] .gslider__main,
  .gslider[data-gs-entrance="pending"] .gslider__thumb-inner {
    opacity: 1;
    transform: none;
  }
  .gslider[data-gs-entrance="pending"] .gslider__dock .gslider__nav { visibility: visible; }
  .gslider[data-gs-entrance="in"] .gslider__thumb-inner,
  .gslider[data-gs-entrance="in"] .gslider__dock .gslider__nav { animation: none; }
}

/* ---- Accessibility floor -------------------------------- */
.gslider :is(a, button, .swiper-slide[tabindex]):focus-visible {
  outline: 3px solid var(--gs-color-focus, var(--gs-color-accent));
  outline-offset: 3px;
}
.gslider__thumbs .swiper-slide:focus-visible .gslider__thumb-inner { outline-color: var(--gs-color-focus, var(--gs-color-accent)); }

:where(.gslider) .visually-hidden {
  position: absolute; inline-size: 1px; block-size: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

@media (prefers-reduced-motion: reduce) {
  :where(.gslider), :where(.gslider) *, :where(.gslider) *::before, :where(.gslider) *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* Pre-init guard: hides the raw slide stack until Swiper mounts. */
.gslider:not(.gslider--ready) .gslider__main .swiper-wrapper > *:not(:first-child) { display: none; }

/* ---- Host-theme hardening --------------------------------
   Themes style a, button and h2 with selectors that outrank single-class
   rules (a:hover, button:focus, .entry-content h2 …) and set properties the
   component never resets (button padding). Restate what matters at
   .gslider scope. Overlay rules still win where they apply. */
.gslider .gslider__nav {
  padding: 0; min-inline-size: 0; min-block-size: 0; box-shadow: none;
  background: var(--gs-nav-background);
  color: var(--gs-nav-color, var(--gs-color-text));
  border: var(--gs-nav-border-width) solid var(--gs-nav-border-color);
}
@media (hover: hover) {
  .gslider .gslider__nav:hover { background: var(--gs-nav-background--hover, var(--gs-color-surface)); }
  /* Not on the overlay layout's arrows over the slide, which keep their own
     colours: these would tie with its rules and, coming later, win. */
  .gslider:not([data-layout="overlay"]) .gslider__nav:hover,
  .gslider .gslider__dock .gslider__nav:hover {
    color: var(--gs-nav-color--hover, var(--gs-nav-color, var(--gs-color-text)));
    border-color: var(--gs-nav-border-color--hover, var(--gs-nav-border-color));
  }
}

/* The button. Every value is: the site's --gs-cta-* token, then --_gs-cta-*,
   then the plugin default. --_gs-cta-* are private slots a framework bridge
   (gerard-slider-acss.css) sets on the button from the framework's own
   button variables; they're undefined everywhere else, so they're skipped.
   Line height, letter-spacing and text-transform have no default: unset,
   they inherit as before. (0,3,0)+ so it also beats builder link rules
   (Beaver Builder's ".fl-row-content-wrap a" at (0,2,1)/(0,3,1)) and
   framework button classes, whatever order the stylesheets load in. */
.gslider .gslider__slide .gslider__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  inline-size: auto;      /* framework buttons can be max-content (ACSS): long labels must wrap */
  max-inline-size: 100%;
  padding-block: var(--gs-cta-padding-block, var(--_gs-cta-padding-block, var(--gs-space-2xs)));
  padding-inline: var(--gs-cta-padding-inline, var(--_gs-cta-padding-inline, var(--gs-space-s)));
  background: var(--gs-cta-background, var(--_gs-cta-background, var(--gs-color-accent)));
  border-width: var(--gs-cta-border-width, var(--_gs-cta-border-width, 0px));
  border-style: var(--_gs-cta-border-style, solid);
  border-color: var(--gs-cta-border-color, var(--gs-cta-background, var(--_gs-cta-border-color, var(--gs-color-accent))));
  border-radius: var(--gs-cta-border-radius, var(--_gs-cta-border-radius, var(--gs-radius)));
  font-size: var(--gs-cta-font-size, var(--_gs-cta-font-size, 0.9375rem));
  font-weight: var(--gs-cta-font-weight, var(--_gs-cta-font-weight, 600));
  line-height: var(--gs-cta-line-height, var(--_gs-cta-line-height));
  letter-spacing: var(--gs-cta-letter-spacing, var(--_gs-cta-letter-spacing));
  text-transform: var(--gs-cta-text-transform, var(--_gs-cta-text-transform));
  transition: opacity var(--gs-transition), background-color var(--gs-transition), color var(--gs-transition), border-color var(--gs-transition);
}
.gslider .gslider__slide .gslider__cta,
.gslider .gslider__slide .gslider__cta:is(:link, :visited, :focus, :active) { color: var(--gs-cta-color, var(--_gs-cta-color, var(--gs-color-on-accent))); text-decoration: none; }
@media (hover: hover) {
  .gslider .gslider__slide .gslider__cta:hover {
    opacity: var(--gs-cta-opacity--hover, var(--_gs-cta-opacity--hover, 0.88));
    background: var(--gs-cta-background--hover, var(--gs-cta-background, var(--_gs-cta-background--hover, var(--_gs-cta-background, var(--gs-color-accent)))));
    color: var(--gs-cta-color--hover, var(--gs-cta-color, var(--_gs-cta-color--hover, var(--_gs-cta-color, var(--gs-color-on-accent)))));
    border-color: var(--gs-cta-border-color--hover, var(--gs-cta-border-color, var(--gs-cta-background--hover, var(--gs-cta-background, var(--_gs-cta-border-color--hover, var(--_gs-cta-border-color, var(--gs-color-accent)))))));
    text-decoration: none;
  }
}
.gslider .gslider__eyebrow,
.gslider .gslider__heading,
.gslider .gslider__desc { margin: 0; }
/* ".entry-content p { color }" and the like outrank a single class. The
   overlay rules (one more attribute selector) still win. */
.gslider .gslider__eyebrow { color: var(--gs-eyebrow-color, var(--gs-color-text-subtle)); font-size: var(--gs-eyebrow-font-size); }
.gslider .gslider__desc { color: var(--gs-desc-color, var(--gs-color-text-muted)); font-size: var(--gs-desc-font-size); }
/* Frameworks round images globally (Automatic.css's "auto radius", themes'
   img rules); the slide image and thumbnails are clipped by their frames. */
.gslider .gslider__media img,
.gslider .gslider__media .gslider__video,
.gslider .gslider__thumb-inner img { border-radius: 0; }
.gslider .gslider__heading {
  font-size: var(--gs-heading-font-size);
  line-height: var(--gs-heading-line-height);
}

/* ---- Right-to-left ----------------------------------------
   Everything else uses logical properties and follows the direction by
   itself; transform-origin and gradient directions have no logical form. */
:where([dir="rtl"]) .gslider__progress-fill { transform-origin: right center; }

/* ---- Print: the entrance never fires, so never print it hidden ---- */
@media print {
  .gslider[data-gs-entrance] .gslider__main,
  .gslider[data-gs-entrance] .gslider__thumb-inner {
    opacity: 1; transform: none; transition: none; animation: none;
  }
  .gslider[data-gs-entrance] .gslider__dock .gslider__nav { visibility: visible; animation: none; }
}
