# Hero slayt gösterisi: ücretsiz Shopify bölümü

> Her birinin masaüstü ve mobil görseli, katmanı, metni ve düğmesi olan en fazla altı slaytlık tam genişlik hero; kaydırma, otomatik oynatma, ok ve noktalar.

Hero slayt gösterisi, en fazla altı tam genişlik slaytı döndüren ücretsiz bir Shopify bölümüdür; her slaytın kendi görseli, mobil görseli, katmanı, başlığı, metni, düğmesi ve içerik konumu vardır. Dokunmatik ekranlarda doğal olarak kaydırılır, duraklatma düğmesi ve klavye kontrolleri vardır; Online Store 2.0 temalarında uygulama olmadan çalışır.

- **Kategori:** Hero ve bannerlar
- **Kullanıldığı yerler:** Ana sayfa, Açılış sayfaları
- **Okuduğu veri:** Yalnızca içerik
- **Boyut:** 3 dosyada 49 KB, küçük bir betikle
- **Lisans:** MIT, © 2026 Lintel
- **Sayfa:** https://lintelagency.com/tr/kaynaklar/shopify-bolumleri/hero-slayt-gosterisi
- **Canlı demo:** https://lintelagency.com/resources/shopify-sections/demo/lib-hero-slideshow.html
- **Eklenme tarihi:** 2026-10-02

## Ne işe yarar

- Koleksiyonlar ya da sezonluk kampanyalar arasında dönen ana sayfa hero’su
- Birkaç ürün serisini sırayla tanıtan açılış sayfası girişi
- Kalıcı en çok satanlar slaytlarının yanında yeni bir seriyi duyurmak

## Tema düzenleyici ayarları

Bölüm tema düzenleyicide “Lib · Hero slideshow” adıyla görünür. Kimlikler, türler, etiketler ve varsayılan değerler bölümün şemasından gelir. Etiketler tema düzenleyicide göründüğü gibi İngilizcedir.

### Content

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `carousel_label` | `text` | Slideshow name for screen readers | Featured collections |  |
| `heading_tag` | `select` | First slide heading tag | h2 | `h1`, `h2`, `h3`, `p` |
| `heading_size` | `select` | Heading size | large | `small`, `medium`, `large`, `xlarge` |

### Slideshow

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `transition` | `select` | Slide transition | slide | `slide`, `fade` |
| `autoplay` | `checkbox` | Autoplay | `true` |  |
| `autoplay_speed` | `range` | Change slides every | `6` | 3–12 s, step 1 |
| `pause_on_hover` | `checkbox` | Pause on hover and keyboard focus | `true` |  |
| `loop` | `checkbox` | Loop back to the first slide | `true` |  |
| `show_arrows` | `checkbox` | Show arrows | `true` |  |
| `pagination` | `select` | Slide indicators | progress | `dots`, `progress`, `none` |

### Layout

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `height` | `select` | Height on desktop | large | `small`, `medium`, `large`, `full`, `adapt` |
| `height_mobile` | `select` | Height on mobile | large | `small`, `medium`, `large`, `full`, `adapt` |
| `section_width` | `select` | Width | full | `full`, `page` |
| `corner_radius` | `range` | Corner radius | `16` | 0–40 px, step 2 |
| `content_width` | `range` | Content max width | `620` | 320–960 px, step 20 |

### Colors

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `color_bg` | `color` | Background | #F5EFE6 |  |
| `color_bg_gradient` | `color_background` | Background gradient | – |  |
| `color_accent` | `color` | Solid button | #FFFFFF |  |
| `color_accent_text` | `color` | Text on solid button | #1C1917 |  |
| `color_controls` | `color` | Arrows and indicators | #FFFFFF |  |

### Spacing and visibility

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `padding_top` | `range` | Top padding on desktop | `0` | 0–200 px, step 4 |
| `padding_bottom` | `range` | Bottom padding on desktop | `0` | 0–200 px, step 4 |
| `padding_top_mobile` | `range` | Top padding on mobile | `0` | 0–160 px, step 4 |
| `padding_bottom_mobile` | `range` | Bottom padding on mobile | `0` | 0–160 px, step 4 |
| `show_on` | `select` | Show on | all | `all`, `desktop`, `mobile` |
| `anchor_id` | `text` | Anchor ID | – |  |

### Motion

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `animate` | `checkbox` | Animate text when a slide appears | `true` |  |

## Bloklar

Toplamda en fazla 6 blok.

### Slide (`slide`)

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `eyebrow` | `text` | Eyebrow | New season |  |
| `heading` | `inline_richtext` | Heading | Made for long tables |  |
| `text` | `richtext` | Text | `<p>Stoneware, linen and candlelight for evenings that run late.</p>` |  |
| `image` | `image_picker` | Desktop image | – |  |
| `image_mobile` | `image_picker` | Mobile image | – |  |
| `overlay_color` | `color` | Overlay color | #1C1917 |  |
| `overlay_opacity` | `range` | Overlay opacity | `30` | 0–90 %, step 5 |
| `button_label` | `text` | Button label | Shop tableware |  |
| `button_url` | `url` | Button link | – |  |
| `button_style` | `select` | Button style | primary | `primary`, `outline`, `text` |
| `button_new_tab` | `checkbox` | Open link in a new tab | `false` |  |
| `slide_url` | `url` | Whole slide link | – |  |
| `content_position` | `select` | Content position on desktop | middle-left | `top-left`, `top-center`, `top-right`, `middle-left`, `middle-center`, `middle-right`, `bottom-left`, `bottom-center`, `bottom-right` |
| `text_alignment` | `text_alignment` | Text alignment on desktop | left |  |
| `content_position_mobile` | `select` | Content position on mobile | bottom | `top`, `middle`, `bottom` |
| `text_alignment_mobile` | `select` | Text alignment on mobile | left | `left`, `center`, `right` |
| `color_text` | `color` | Text | #FFFFFF |  |

## Kurulum

### Shopify yönetim panelinde

1. Canlı temanızda değil, bir kopyasında çalışın: Shopify yönetim panelinde **Online Mağaza > Temalar** sayfasına gidin, mevcut temanızın **…** menüsünü açın ve **Kopya oluştur**’u seçin.
2. Kopyada **…** menüsünü açın ve **Kodu düzenle**’yi seçin.
3. `sections` klasörüne `lib-hero-slideshow.liquid` adında yeni bir dosya ekleyin, aşağıdaki kaynak koddan `sections/lib-hero-slideshow.liquid` içeriğini yapıştırıp kaydedin.
4. `lib-image.liquid` ve `lib-button.liquid` dosyalarını da aynı şekilde `snippets` klasörüne ekleyin. Başka bir Lib bölümünden gelen aynı adlı bir snippet zaten varsa aynı dosyadır; tek kopya yeterli.
5. Kopyada **Özelleştir**’i açın, **Bölüm ekle**’yi seçin ve **Lib · Hero slideshow** bölümünü ekleyin. Örnek içeriği kendi içeriğinizle değiştirin, renkleri ayarlayın.
6. Kopyayı önizleyin, her şey doğru göründüğünde yayınlayın.

### Shopify CLI ile

Yerel tema klasörünüzde dosyaları indirin ve yalnızca bunları yayında olmayan bir temaya gönderin (temanın kimliğini `shopify theme list` gösterir):

```sh
curl -fsSL -o sections/lib-hero-slideshow.liquid https://lintelagency.com/resources/shopify-sections/files/lib-hero-slideshow.liquid
curl -fsSL -o snippets/lib-image.liquid https://lintelagency.com/resources/shopify-sections/files/lib-image.liquid
curl -fsSL -o snippets/lib-button.liquid https://lintelagency.com/resources/shopify-sections/files/lib-button.liquid
shopify theme push --theme <unpublished-theme-id> --only sections/lib-hero-slideshow.liquid --only snippets/lib-image.liquid --only snippets/lib-button.liquid
```

Canlı temaya asla göndermeyin: her zaman yayında olmayan bir temanın kimliğini verin, `--live` ya da `--allow-live` kullanmayın. Ardından bölümü yukarıdaki gibi tema düzenleyicide ekleyin.

## Dosyalar

- [sections/lib-hero-slideshow.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-hero-slideshow.liquid): `sections/` klasörüne
- [snippets/lib-image.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-image.liquid): `snippets/` klasörüne
- [snippets/lib-button.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-button.liquid): `snippets/` klasörüne

## Sık sorulan sorular

### Kaç slayt ekleyebilirim?

En fazla altı. Her slayt; kendi masaüstü ve mobil görseli, katman rengi ve opaklığı, üst başlığı, başlığı, metni, düğmesi, içerik konumu ve metin rengi olan bir bloktur.

### Erişilebilir mi?

Slayt gösterisi, etiketli slaytlarla bir carousel olarak işaretlenmiştir. Oklar ve noktalar gerçek düğmelerdir (noktalar "Go to slide 1" gibi okunur), kontroller odaktayken ok tuşları slaytlar arasında geçiş yapar ve gizli slaytlara Tab ile girilemez. Otomatik oynatma açıkken bir duraklatma düğmesi vardır; slayt değişiklikleri yalnızca otomatik oynatma çalışmıyorken ekran okuyuculara sessizce duyurulur.

### Azaltılmış hareket tercihinde ne olur?

Cihazı azaltılmış hareket isteyen ziyaretçilerde otomatik oynatma başlamaz, slaytlar yumuşak kaydırma ya da solma olmadan değişir ve metin animasyonu kapanır. Ziyaretçi otomatik oynatmayı başlatmak için yine oynat düğmesine basabilir.

### Otomatik oynatma duraklar mı?

Evet. Fare slayt gösterisinin üzerindeyken ya da klavye odağı içindeyken (bu kapatılabilir), slayt gösterisi görünümün dışına kaydırıldığında ya da tarayıcı sekmesi gizlendiğinde ve ziyaretçi duraklat düğmesine bastığında durur. Döngü kapalıysa son slaytta durur.

### Kaydırma nasıl çalışır?

Kaydırma geçişi tarayıcının doğal scroll snapping özelliğini kullanır; böylece dokunmatik kaydırma ve trackpad hareketleri script yüklenmeden de çalışır. Solma geçişi yatay kaydırmaları pointer olaylarıyla işler.

### Sayfayı yavaşlatır mı?

Bölüm sayfadaki ilk iki bölümden biriyse ilk slaytın görseli hemen ve yüksek fetch önceliğiyle yüklenir; diğer tüm slayt görselleri lazy-load ile yüklenir. Script küçüktür; kütüphane içermeyen vanilla JavaScript’tir.

## Kaynak kod

### sections/lib-hero-slideshow.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{%- comment -%}
  Hero slideshow: up to 6 full-bleed slides, each with its own desktop and mobile image, overlay,
  eyebrow, heading, text, button, content position and text color.
  Slide transition uses native scroll-snap (swipe and trackpad work without script) or a cross-fade.
  Autoplay with a pause button, pause on hover and keyboard focus, off under prefers-reduced-motion.
  Arrows, dots or progress bars; optional loop. Several instances per page are independent.
  Depends on: snippets/lib-button.liquid, snippets/lib-image.liquid
{%- endcomment -%}

{%- liquid
  assign s = section.settings
  assign heading_tag = s.heading_tag | default: 'h2'
  assign later_tag = heading_tag
  if heading_tag == 'h1'
    assign later_tag = 'h2'
  endif

  assign slide_count = section.blocks.size
  assign autoplay = false
  if s.autoplay and slide_count > 1
    assign autoplay = true
  endif
  assign has_controls = false
  if slide_count > 1
    if s.show_arrows or s.pagination != 'none' or autoplay
      assign has_controls = true
    endif
  endif

  assign first = section.blocks.first.settings
  assign ratio_d = first.image | default: first.image_mobile
  assign ratio_m = first.image_mobile | default: first.image
-%}

<div
  class="lib-hero-slideshow lib-hero-slideshow--{{ s.section_width }}"
  {% if s.anchor_id != blank %}
    id="{{ s.anchor_id | handleize }}"
  {% endif %}
  data-show="{{ s.show_on }}"
  data-height="{{ s.height }}"
  data-height-m="{{ s.height_mobile }}"
  {% if s.animate %}
    data-animate
  {% endif %}
  style="
    --lib-bg: {{ s.color_bg }};
    {% if s.color_bg_gradient != blank %}--lib-bg-image: {{ s.color_bg_gradient }};{% endif %}
    --lib-accent: {{ s.color_accent }};
    --lib-accent-text: {{ s.color_accent_text }};
    --lib-controls: {{ s.color_controls }};
    --lib-interval: {{ s.autoplay_speed }}s;
    --lib-content-w: {{ s.content_width }}px;
    --lib-radius-frame: {{ s.corner_radius }}px;
    {% if ratio_d != blank %}--lib-ratio: {{ ratio_d.width }} / {{ ratio_d.height }};{% endif %}
    {% if ratio_m != blank %}--lib-ratio-m: {{ ratio_m.width }} / {{ ratio_m.height }};{% endif %}
    --lib-pt: {{ s.padding_top }}px;
    --lib-pb: {{ s.padding_bottom }}px;
    --lib-pt-m: {{ s.padding_top_mobile }}px;
    --lib-pb-m: {{ s.padding_bottom_mobile }}px;
  "
>
  {%- if slide_count > 0 -%}
    <lib-hero-slideshow-carousel
      class="lib-hero-slideshow__carousel"
      role="region"
      aria-roledescription="carousel"
      {% if s.carousel_label != blank %}
        aria-label="{{ s.carousel_label | escape }}"
      {% endif %}
      data-transition="{{ s.transition }}"
      data-interval="{{ s.autoplay_speed }}"
      {% if autoplay %}
        data-autoplay
      {% endif %}
      {% if s.pause_on_hover %}
        data-pause-hover
      {% endif %}
      {% if s.loop %}
        data-loop
      {% endif %}
      {% if has_controls %}
        data-has-controls
      {% endif %}
    >
      <div
        class="lib-hero-slideshow__track"
        id="LibSlideshowTrack-{{ section.id }}"
        data-track
        aria-live="{% if autoplay %}off{% else %}polite{% endif %}"
      >
        {%- for block in section.blocks -%}
          {%- liquid
            assign b = block.settings
            assign eager = false
            if forloop.first and section.index <= 2
              assign eager = true
            endif
            assign tag = later_tag
            if forloop.first
              assign tag = heading_tag
            endif
            assign slide_link = false
            if b.button_label == blank and b.slide_url != blank
              assign slide_link = true
            endif
            assign link_label = b.heading | strip_html | strip
          -%}
          <div
            class="lib-hero-slideshow__slide"
            id="LibSlide-{{ section.id }}-{{ forloop.index }}"
            role="group"
            aria-roledescription="slide"
            aria-label="{{ forloop.index }} of {{ forloop.length }}"
            data-slide
            {% if forloop.first %}
              data-active
            {% endif %}
            style="
              --lib-text: {{ b.color_text }};
              --lib-overlay: {{ b.overlay_color }};
              --lib-overlay-o: {{ b.overlay_opacity | divided_by: 100.0 }};
            "
            {{ block.shopify_attributes }}
          >
            <div class="lib-hero-slideshow__media">
              {%- render 'lib-image',
                image: b.image,
                image_mobile: b.image_mobile,
                class: 'lib-hero-slideshow__img',
                sizes: '100vw',
                eager: eager
              -%}
            </div>
            <div class="lib-hero-slideshow__overlay" aria-hidden="true"></div>

            {%- if slide_link -%}
              <a
                class="lib-hero-slideshow__link"
                href="{{ b.slide_url }}"
                {% if link_label != blank %}
                  aria-label="{{ link_label | escape }}"
                {% endif %}
              ></a>
            {%- endif -%}

            <div
              class="lib-hero-slideshow__content"
              data-pos="{{ b.content_position }}"
              data-pos-m="{{ b.content_position_mobile }}"
              data-align-m="{{ b.text_alignment_mobile }}"
            >
              <div
                class="lib-hero-slideshow__box"
                data-align="{{ b.text_alignment }}"
                data-align-m="{{ b.text_alignment_mobile }}"
              >
                {%- if b.eyebrow != blank -%}
                  <p class="lib-hero-slideshow__eyebrow">{{ b.eyebrow | escape }}</p>
                {%- endif -%}
                {%- if b.heading != blank -%}
                  <{{ tag }} class="lib-hero-slideshow__heading lib-hero-slideshow__heading--{{ s.heading_size }}">
                    {{- b.heading -}}
                  </{{ tag }}>
                {%- endif -%}
                {%- if b.text != blank -%}
                  <div class="lib-hero-slideshow__text">{{ b.text }}</div>
                {%- endif -%}
                {%- if b.button_label != blank -%}
                  <div class="lib-hero-slideshow__actions">
                    {%- render 'lib-button',
                      label: b.button_label,
                      url: b.button_url,
                      style: b.button_style,
                      new_tab: b.button_new_tab
                    -%}
                  </div>
                {%- endif -%}
              </div>
            </div>
          </div>
        {%- endfor -%}
      </div>

      {%- if has_controls -%}
        <div class="lib-hero-slideshow__controls" data-controls>
          {%- if s.pagination != 'none' -%}
            <div class="lib-hero-slideshow__dots" data-style="{{ s.pagination }}">
              {%- for block in section.blocks -%}
                <button
                  type="button"
                  class="lib-hero-slideshow__dot"
                  aria-label="Go to slide {{ forloop.index }}"
                  aria-controls="LibSlide-{{ section.id }}-{{ forloop.index }}"
                  {% if forloop.first %}
                    aria-current="true"
                  {% endif %}
                  data-dot
                >
                  <span class="lib-hero-slideshow__bar" aria-hidden="true"></span>
                </button>
              {%- endfor -%}
            </div>
          {%- endif -%}

          <div class="lib-hero-slideshow__nav">
            {%- if autoplay -%}
              <button
                type="button"
                class="lib-hero-slideshow__btn"
                aria-label="Pause slideshow"
                data-play
                data-state="playing"
              >
                <svg class="lib-hero-slideshow__icon-pause" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" focusable="false">
                  <path d="M5.5 3.5v9M10.5 3.5v9" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
                </svg>
                <svg class="lib-hero-slideshow__icon-play" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" focusable="false">
                  <path d="M5 3.2v9.6L12.6 8Z" fill="currentColor"/>
                </svg>
              </button>
            {%- endif -%}
            {%- if s.show_arrows -%}
              <button
                type="button"
                class="lib-hero-slideshow__btn lib-hero-slideshow__btn--arrow"
                aria-label="Previous slide"
                aria-controls="LibSlideshowTrack-{{ section.id }}"
                data-prev
                {% unless s.loop %}
                  disabled
                {% endunless %}
              >
                <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" focusable="false">
                  <path d="M13 8H4M7.5 4.5 4 8l3.5 3.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
                </svg>
              </button>
              <button
                type="button"
                class="lib-hero-slideshow__btn lib-hero-slideshow__btn--arrow"
                aria-label="Next slide"
                aria-controls="LibSlideshowTrack-{{ section.id }}"
                data-next
              >
                <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" focusable="false">
                  <path d="M3 8h9M8.5 4.5 12 8l-3.5 3.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
                </svg>
              </button>
            {%- endif -%}
          </div>
        </div>
      {%- endif -%}
    </lib-hero-slideshow-carousel>
  {%- elsif request.design_mode -%}
    <div class="lib-hero-slideshow__carousel">
      <div class="lib-hero-slideshow__slide lib-hero-slideshow__slide--empty" style="--lib-text: #FFFFFF; --lib-overlay: #1C1917; --lib-overlay-o: 0.3;">
        <div class="lib-hero-slideshow__media">
          {{ 'lifestyle-1' | placeholder_svg_tag: 'lib-hero-slideshow__img' }}
        </div>
        <div class="lib-hero-slideshow__overlay" aria-hidden="true"></div>
        <div class="lib-hero-slideshow__content" data-pos="middle-center" data-pos-m="middle" data-align-m="center">
          <div class="lib-hero-slideshow__box" data-align="center" data-align-m="center">
            <p class="lib-hero-slideshow__heading lib-hero-slideshow__heading--small">Add a slide to start the slideshow</p>
          </div>
        </div>
      </div>
    </div>
  {%- endif -%}
</div>

{% stylesheet %}
  .lib-hero-slideshow {
    background-color: var(--lib-bg);
    background-image: var(--lib-bg-image, none);
    padding: var(--lib-pt-m) 0 var(--lib-pb-m);
  }
  .lib-hero-slideshow--page { padding-inline: 1rem; }
  .lib-hero-slideshow__carousel {
    position: relative;
    display: block;
    overflow: hidden;
    isolation: isolate;
    background: #292524;
  }
  .lib-hero-slideshow--page .lib-hero-slideshow__carousel {
    max-width: 1200px;
    margin-inline: auto;
    border-radius: var(--lib-radius-frame);
  }

  /* Track: native horizontal scroll-snap; one slide per view. */
  .lib-hero-slideshow__track {
    position: relative;
    display: flex;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .lib-hero-slideshow__track::-webkit-scrollbar { display: none; }
  .lib-hero-slideshow__slide {
    position: relative;
    flex: 0 0 100%;
    display: grid;
    min-width: 0;
    min-height: 600px;
    isolation: isolate;
    scroll-snap-align: start;
    scroll-snap-stop: always;
    color: var(--lib-text);
  }

  /* Fade: slides stack in one cell and cross-fade. */
  .lib-hero-slideshow__carousel[data-transition='fade'] .lib-hero-slideshow__track {
    display: grid;
    overflow: hidden;
    scroll-snap-type: none;
    touch-action: pan-y;
  }
  .lib-hero-slideshow__carousel[data-transition='fade'] .lib-hero-slideshow__slide {
    grid-area: 1 / 1;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.8s ease, visibility 0s linear 0.8s;
  }
  .lib-hero-slideshow__carousel[data-transition='fade'] .lib-hero-slideshow__slide[data-active] {
    z-index: 1;
    opacity: 1;
    visibility: visible;
    transition: opacity 0.8s ease;
  }

  /* Height: mobile first, then desktop. "adapt" follows the first slide's image. */
  .lib-hero-slideshow[data-height-m='small'] .lib-hero-slideshow__slide { min-height: 360px; }
  .lib-hero-slideshow[data-height-m='medium'] .lib-hero-slideshow__slide { min-height: 480px; }
  .lib-hero-slideshow[data-height-m='large'] .lib-hero-slideshow__slide { min-height: 600px; }
  .lib-hero-slideshow[data-height-m='full'] .lib-hero-slideshow__slide { min-height: 100vh; min-height: 100svh; }
  .lib-hero-slideshow[data-height-m='adapt'] .lib-hero-slideshow__slide { min-height: auto; aspect-ratio: var(--lib-ratio-m, 4 / 5); }
  @media (min-width: 750px) {
    .lib-hero-slideshow {
      padding-top: var(--lib-pt);
      padding-bottom: var(--lib-pb);
    }
    .lib-hero-slideshow[data-height] .lib-hero-slideshow__slide { aspect-ratio: auto; }
    .lib-hero-slideshow[data-height='small'] .lib-hero-slideshow__slide { min-height: 440px; }
    .lib-hero-slideshow[data-height='medium'] .lib-hero-slideshow__slide { min-height: 600px; }
    .lib-hero-slideshow[data-height='large'] .lib-hero-slideshow__slide { min-height: 760px; }
    .lib-hero-slideshow[data-height='full'] .lib-hero-slideshow__slide { min-height: 100vh; min-height: 100svh; }
    .lib-hero-slideshow[data-height='adapt'] .lib-hero-slideshow__slide { min-height: auto; aspect-ratio: var(--lib-ratio, 16 / 9); }
  }

  /* Visibility */
  @media (max-width: 749px) {
    .lib-hero-slideshow[data-show='desktop'] { display: none; }
  }
  @media (min-width: 750px) {
    .lib-hero-slideshow[data-show='mobile'] { display: none; }
  }

  /* Media, overlay, whole-slide link */
  .lib-hero-slideshow__media,
  .lib-hero-slideshow__overlay,
  .lib-hero-slideshow__link {
    position: absolute;
    inset: 0;
  }
  .lib-hero-slideshow__media { z-index: -2; overflow: hidden; border-radius: inherit; }
  .lib-hero-slideshow__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  .lib-hero-slideshow__img:is(svg) { fill: color-mix(in srgb, #fff 18%, transparent); background: #57534e; }
  .lib-hero-slideshow__overlay {
    z-index: -1;
    background: var(--lib-overlay);
    opacity: var(--lib-overlay-o);
    pointer-events: none;
  }
  .lib-hero-slideshow__link { z-index: 2; }
  .lib-hero-slideshow__link:focus-visible {
    outline: 3px solid var(--lib-text);
    outline-offset: -6px;
  }

  /* Content position: mobile uses data-pos-m, desktop the 9-way data-pos. */
  .lib-hero-slideshow__content {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    min-width: 0;
    padding: 2rem 1.25rem;
  }
  .lib-hero-slideshow__carousel[data-has-controls] .lib-hero-slideshow__content { padding-bottom: 5rem; }
  .lib-hero-slideshow__link ~ .lib-hero-slideshow__content { pointer-events: none; }
  .lib-hero-slideshow__content[data-pos-m='top'] { justify-content: flex-start; }
  .lib-hero-slideshow__content[data-pos-m='middle'] { justify-content: center; }
  .lib-hero-slideshow__content[data-pos-m='bottom'] { justify-content: flex-end; }
  .lib-hero-slideshow__content[data-align-m='left'] { align-items: flex-start; }
  .lib-hero-slideshow__content[data-align-m='center'] { align-items: center; }
  .lib-hero-slideshow__content[data-align-m='right'] { align-items: flex-end; }
  @media (min-width: 750px) {
    .lib-hero-slideshow__content,
    .lib-hero-slideshow__controls {
      padding-inline: clamp(2rem, 5vw, 4.5rem);
    }
    .lib-hero-slideshow--full .lib-hero-slideshow__content,
    .lib-hero-slideshow--full .lib-hero-slideshow__controls {
      padding-inline: max(clamp(2rem, 5vw, 4.5rem), calc((100% - 1200px) / 2 + 1rem));
    }
    .lib-hero-slideshow__content { padding-block: clamp(2.5rem, 5vw, 4.5rem); }
    .lib-hero-slideshow__carousel[data-has-controls] .lib-hero-slideshow__content { padding-bottom: 6.5rem; }
    .lib-hero-slideshow__content[data-pos^='top'] { justify-content: flex-start; }
    .lib-hero-slideshow__content[data-pos^='middle'] { justify-content: center; }
    .lib-hero-slideshow__content[data-pos^='bottom'] { justify-content: flex-end; }
    .lib-hero-slideshow__content[data-pos$='left'] { align-items: flex-start; }
    .lib-hero-slideshow__content[data-pos$='center'] { align-items: center; }
    .lib-hero-slideshow__content[data-pos$='right'] { align-items: flex-end; }
  }

  .lib-hero-slideshow__box {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    width: 100%;
    max-width: var(--lib-content-w);
    text-align: left;
  }
  .lib-hero-slideshow__box[data-align-m='center'] { align-items: center; text-align: center; }
  .lib-hero-slideshow__box[data-align-m='right'] { align-items: flex-end; text-align: right; }
  @media (min-width: 750px) {
    .lib-hero-slideshow__box { width: auto; }
    .lib-hero-slideshow__box[data-align='left'] { align-items: flex-start; text-align: left; }
    .lib-hero-slideshow__box[data-align='center'] { align-items: center; text-align: center; }
    .lib-hero-slideshow__box[data-align='right'] { align-items: flex-end; text-align: right; }
  }
  .lib-hero-slideshow__eyebrow {
    margin: 0 0 1rem;
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
  }
  .lib-hero-slideshow__heading {
    margin: 0;
    font-size: clamp(2.25rem, 5vw, 4rem);
    line-height: 1.05;
    letter-spacing: -0.025em;
    text-wrap: balance;
    overflow-wrap: anywhere;
  }
  .lib-hero-slideshow__heading--small { font-size: clamp(1.75rem, 3vw, 2.5rem); }
  .lib-hero-slideshow__heading--medium { font-size: clamp(2rem, 4vw, 3.25rem); }
  .lib-hero-slideshow__heading--xlarge { font-size: clamp(2.75rem, 7vw, 5.5rem); }
  .lib-hero-slideshow__text {
    margin-top: 1.125rem;
    font-size: 1.0625rem;
    line-height: 1.6;
    opacity: 0.88;
  }
  .lib-hero-slideshow__text > :first-child { margin-top: 0; }
  .lib-hero-slideshow__text > :last-child { margin-bottom: 0; }
  .lib-hero-slideshow__text a { color: inherit; }
  .lib-hero-slideshow__actions { margin-top: 1.75rem; }

  /* Controls: pagination on one side, pause and arrows on the other. */
  .lib-hero-slideshow__controls {
    position: absolute;
    inset: auto 0 0;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0 1.25rem 1.25rem;
    color: var(--lib-controls);
    pointer-events: none;
  }
  .lib-hero-slideshow__controls > * { pointer-events: auto; }
  .lib-hero-slideshow__dots { display: flex; flex-wrap: wrap; align-items: center; }
  .lib-hero-slideshow__nav { display: flex; gap: 0.5rem; margin-inline-start: auto; }
  .lib-hero-slideshow__dot {
    display: grid;
    place-items: center;
    min-width: 24px;
    height: 32px;
    padding: 0 4px;
    border: 0;
    background: none;
    color: inherit;
    cursor: pointer;
  }
  .lib-hero-slideshow__bar {
    position: relative;
    display: block;
    width: 8px;
    height: 8px;
    border-radius: 999px;
    background: currentColor;
    opacity: 0.45;
    overflow: hidden;
    transition: width 0.3s ease, opacity 0.3s ease;
  }
  .lib-hero-slideshow__dot:hover .lib-hero-slideshow__bar { opacity: 0.8; }
  .lib-hero-slideshow__dots[data-style='dots'] .lib-hero-slideshow__dot[aria-current='true'] .lib-hero-slideshow__bar {
    width: 24px;
    opacity: 1;
  }
  .lib-hero-slideshow__dots[data-style='progress'] .lib-hero-slideshow__bar {
    width: 36px;
    height: 2px;
    background: color-mix(in srgb, currentColor 40%, transparent);
    opacity: 1;
  }
  .lib-hero-slideshow__dots[data-style='progress'] .lib-hero-slideshow__bar::after {
    content: '';
    position: absolute;
    inset: 0;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: left;
  }
  .lib-hero-slideshow__dots[data-style='progress'] .lib-hero-slideshow__dot[aria-current='true'] .lib-hero-slideshow__bar::after { transform: none; }
  .lib-hero-slideshow__carousel[data-playing] .lib-hero-slideshow__dots[data-style='progress'] .lib-hero-slideshow__dot[aria-current='true'] .lib-hero-slideshow__bar::after {
    animation: lib-hero-slideshow-fill var(--lib-interval) linear both;
  }
  .lib-hero-slideshow__carousel[data-held] .lib-hero-slideshow__bar::after { animation-play-state: paused !important; }
  @keyframes lib-hero-slideshow-fill {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
  }
  .lib-hero-slideshow__btn {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    color: inherit;
    background: color-mix(in srgb, #000 22%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 45%, transparent);
    backdrop-filter: blur(6px);
    cursor: pointer;
    transition: background-color 0.2s ease, opacity 0.2s ease;
  }
  .lib-hero-slideshow__btn:hover { background: color-mix(in srgb, #000 40%, transparent); }
  .lib-hero-slideshow__btn:disabled { opacity: 0.4; cursor: default; }
  .lib-hero-slideshow__btn[data-state='playing'] .lib-hero-slideshow__icon-play,
  .lib-hero-slideshow__btn[data-state='paused'] .lib-hero-slideshow__icon-pause { display: none; }
  .lib-hero-slideshow__btn:focus-visible,
  .lib-hero-slideshow__dot:focus-visible {
    outline: 2px solid var(--lib-controls);
    outline-offset: 2px;
    border-radius: 999px;
  }
  @media (max-width: 749px) {
    .lib-hero-slideshow__btn { width: 40px; height: 40px; }
  }

  /* Motion: copy rises in each time a slide becomes active. */
  .lib-hero-slideshow[data-animate] .lib-hero-slideshow__slide[data-active] .lib-hero-slideshow__box > * {
    animation: lib-hero-slideshow-rise 0.8s cubic-bezier(0.2, 0.7, 0.2, 1) both;
  }
  .lib-hero-slideshow[data-animate] .lib-hero-slideshow__slide[data-active] .lib-hero-slideshow__box > :nth-child(2) { animation-delay: 0.08s; }
  .lib-hero-slideshow[data-animate] .lib-hero-slideshow__slide[data-active] .lib-hero-slideshow__box > :nth-child(3) { animation-delay: 0.16s; }
  .lib-hero-slideshow[data-animate] .lib-hero-slideshow__slide[data-active] .lib-hero-slideshow__box > :nth-child(n + 4) { animation-delay: 0.24s; }
  @keyframes lib-hero-slideshow-rise {
    from { opacity: 0; transform: translateY(14px); }
  }
  @media (prefers-reduced-motion: reduce) {
    .lib-hero-slideshow__track { scroll-behavior: auto; }
    .lib-hero-slideshow__carousel[data-transition='fade'] .lib-hero-slideshow__slide,
    .lib-hero-slideshow__bar,
    .lib-hero-slideshow__btn { transition: none; }
    .lib-hero-slideshow[data-animate] .lib-hero-slideshow__slide[data-active] .lib-hero-slideshow__box > * { animation: none; }
  }
{% endstylesheet %}

{% javascript %}
  if (!customElements.get('lib-hero-slideshow-carousel')) {
    class LibHeroSlideshowCarousel extends HTMLElement {
      connectedCallback() {
        this.teardown();
        this.track = this.querySelector('[data-track]');
        this.slides = this.track ? Array.from(this.track.children).filter((el) => el.hasAttribute('data-slide')) : [];
        if (this.slides.length < 2) return;

        this.fade = this.dataset.transition === 'fade';
        this.loop = this.hasAttribute('data-loop');
        this.interval = Math.max(2, Number(this.dataset.interval) || 6) * 1000;
        this.dots = Array.from(this.querySelectorAll('[data-dot]'));
        this.prevBtn = this.querySelector('[data-prev]');
        this.nextBtn = this.querySelector('[data-next]');
        this.playBtn = this.querySelector('[data-play]');
        this.reduced = window.matchMedia('(prefers-reduced-motion: reduce)');
        this.index = 0;
        this.holds = new Set();
        this.remaining = this.interval;
        this.timer = null;
        this.startedAt = 0;
        this.playing = this.hasAttribute('data-autoplay') && !this.reduced.matches;

        this.ac = new AbortController();
        const opt = { signal: this.ac.signal };

        if (this.prevBtn) this.prevBtn.addEventListener('click', () => this.go(this.index - 1), opt);
        if (this.nextBtn) this.nextBtn.addEventListener('click', () => this.go(this.index + 1), opt);
        this.dots.forEach((dot, i) => dot.addEventListener('click', () => this.go(i), opt));
        if (this.playBtn) this.playBtn.addEventListener('click', () => this.setPlaying(!this.playing), opt);

        // Arrow keys move between slides while focus is on the controls.
        this.addEventListener(
          'keydown',
          (e) => {
            if (!(e.target instanceof Element) || !e.target.closest('[data-controls]')) return;
            const rtl = getComputedStyle(this).direction === 'rtl';
            let step = 0;
            if (e.key === 'ArrowRight') step = rtl ? -1 : 1;
            if (e.key === 'ArrowLeft') step = rtl ? 1 : -1;
            if (!step) return;
            e.preventDefault();
            this.go(this.index + step);
            const dot = this.dots[this.index];
            if (dot && e.target.hasAttribute('data-dot')) dot.focus();
          },
          opt
        );

        if (this.fade) {
          this.bindSwipe(opt);
        } else {
          this.track.addEventListener('scroll', () => this.onScroll(), { passive: true, signal: this.ac.signal });
        }

        if (this.hasAttribute('data-pause-hover')) {
          this.addEventListener('pointerenter', (e) => e.pointerType === 'mouse' && this.hold('hover'), opt);
          this.addEventListener('pointerleave', (e) => e.pointerType === 'mouse' && this.release('hover'), opt);
          this.addEventListener(
            'focusin',
            (e) => {
              if (e.target instanceof Element && e.target.matches(':focus-visible')) this.hold('focus');
            },
            opt
          );
          this.addEventListener('focusout', (e) => !this.contains(e.relatedTarget) && this.release('focus'), opt);
        }

        document.addEventListener('visibilitychange', () => (document.hidden ? this.hold('hidden') : this.release('hidden')), opt);
        if ('IntersectionObserver' in window) {
          this.io = new IntersectionObserver(
            (entries) => entries.forEach((en) => (en.isIntersecting ? this.release('offscreen') : this.hold('offscreen'))),
            { threshold: 0.2 }
          );
          this.io.observe(this);
        }
        if (this.reduced.addEventListener) {
          this.reduced.addEventListener('change', () => this.reduced.matches && this.setPlaying(false), opt);
        }

        // Theme editor: show the selected slide and hold autoplay while it is selected.
        document.addEventListener(
          'shopify:block:select',
          (e) => {
            const i = this.slides.indexOf(e.target);
            if (i < 0) return;
            this.hold('editor');
            this.go(i);
          },
          opt
        );
        document.addEventListener('shopify:block:deselect', (e) => this.slides.includes(e.target) && this.release('editor'), opt);

        this.setActive(0, false);
        this.update();
      }

      disconnectedCallback() {
        this.teardown();
      }

      teardown() {
        if (this.ac) this.ac.abort();
        if (this.io) this.io.disconnect();
        clearTimeout(this.timer);
        clearTimeout(this.scrollTimer);
        this.ac = null;
        this.io = null;
        this.timer = null;
      }

      go(target) {
        const n = this.slides.length;
        let i = this.loop ? ((target % n) + n) % n : Math.max(0, Math.min(n - 1, target));
        if (i === this.index) return;
        this.setActive(i, true);
        this.update();
      }

      setActive(i, scroll) {
        this.index = i;
        this.slides.forEach((slide, k) => {
          slide.toggleAttribute('data-active', k === i);
          slide.inert = k !== i;
        });
        this.dots.forEach((dot, k) => (k === i ? dot.setAttribute('aria-current', 'true') : dot.removeAttribute('aria-current')));
        if (!this.loop) {
          if (this.prevBtn) this.prevBtn.disabled = i === 0;
          if (this.nextBtn) this.nextBtn.disabled = i === this.slides.length - 1;
        }
        if (scroll && !this.fade) {
          const left = this.slides[i].offsetLeft - this.slides[0].offsetLeft;
          this.track.scrollTo({ left, behavior: this.reduced.matches ? 'auto' : 'smooth' });
        }
        this.remaining = this.interval;
      }

      onScroll() {
        clearTimeout(this.scrollTimer);
        this.scrollTimer = setTimeout(() => {
          const width = this.track.clientWidth || 1;
          const i = Math.round(Math.abs(this.track.scrollLeft) / width);
          if (i !== this.index && this.slides[i]) {
            this.setActive(i, false);
            this.update();
          }
        }, 90);
      }

      bindSwipe(opt) {
        let x = null;
        let y = null;
        let swiped = false;
        this.track.addEventListener(
          'pointerdown',
          (e) => {
            if (!e.isPrimary) return;
            x = e.clientX;
            y = e.clientY;
            swiped = false;
          },
          opt
        );
        this.track.addEventListener(
          'pointerup',
          (e) => {
            if (x === null) return;
            const dx = e.clientX - x;
            const dy = e.clientY - y;
            x = null;
            if (Math.abs(dx) < 40 || Math.abs(dx) < Math.abs(dy)) return;
            swiped = true;
            const rtl = getComputedStyle(this).direction === 'rtl';
            this.go(this.index + ((dx < 0) !== rtl ? 1 : -1));
          },
          opt
        );
        this.track.addEventListener('pointercancel', () => (x = null), opt);
        this.track.addEventListener(
          'click',
          (e) => {
            if (!swiped) return;
            swiped = false;
            e.preventDefault();
            e.stopPropagation();
          },
          { capture: true, signal: opt.signal }
        );
      }

      setPlaying(on) {
        this.playing = on;
        this.remaining = this.interval;
        const dot = this.dots[this.index];
        if (on && dot) {
          dot.removeAttribute('aria-current');
          void dot.offsetWidth;
          dot.setAttribute('aria-current', 'true');
        }
        this.update();
      }

      hold(reason) {
        if (this.holds.has(reason)) return;
        this.pauseClock();
        this.holds.add(reason);
        this.update();
      }

      release(reason) {
        if (!this.holds.delete(reason)) return;
        this.update();
      }

      pauseClock() {
        if (this.timer) this.remaining = Math.max(0, this.remaining - (performance.now() - this.startedAt));
      }

      advance() {
        this.timer = null;
        if (!this.loop && this.index === this.slides.length - 1) {
          this.setPlaying(false);
          return;
        }
        this.go(this.index + 1);
      }

      update() {
        if (!this.track) return;
        const running = this.playing && this.holds.size === 0;
        this.toggleAttribute('data-playing', this.playing);
        this.toggleAttribute('data-held', this.playing && !running);
        this.track.setAttribute('aria-live', this.playing ? 'off' : 'polite');
        if (this.playBtn) {
          this.playBtn.dataset.state = this.playing ? 'playing' : 'paused';
          this.playBtn.setAttribute('aria-label', this.playing ? 'Pause slideshow' : 'Play slideshow');
        }
        clearTimeout(this.timer);
        this.timer = null;
        if (running) {
          this.startedAt = performance.now();
          this.timer = setTimeout(() => this.advance(), this.remaining);
        }
      }
    }
    customElements.define('lib-hero-slideshow-carousel', LibHeroSlideshowCarousel);
  }
{% endjavascript %}

{% schema %}
{
  "name": "Lib · Hero slideshow",
  "tag": "section",
  "class": "lib-section",
  "max_blocks": 6,
  "settings": [
    { "type": "header", "content": "Content" },
    {
      "type": "text",
      "id": "carousel_label",
      "label": "Slideshow name for screen readers",
      "info": "Announced when someone reaches the slideshow, e.g. \"Featured collections\".",
      "default": "Featured collections"
    },
    {
      "type": "select",
      "id": "heading_tag",
      "label": "First slide heading tag",
      "info": "Later slides use H2 when this is H1, so the page keeps a single H1.",
      "options": [
        { "value": "h1", "label": "H1" },
        { "value": "h2", "label": "H2" },
        { "value": "h3", "label": "H3" },
        { "value": "p", "label": "Paragraph" }
      ],
      "default": "h2"
    },
    {
      "type": "select",
      "id": "heading_size",
      "label": "Heading size",
      "options": [
        { "value": "small", "label": "Small" },
        { "value": "medium", "label": "Medium" },
        { "value": "large", "label": "Large" },
        { "value": "xlarge", "label": "Extra large" }
      ],
      "default": "large"
    },

    { "type": "header", "content": "Slideshow" },
    {
      "type": "select",
      "id": "transition",
      "label": "Slide transition",
      "options": [
        { "value": "slide", "label": "Slide" },
        { "value": "fade", "label": "Fade" }
      ],
      "default": "slide"
    },
    { "type": "checkbox", "id": "autoplay", "label": "Autoplay", "info": "Always off for visitors who ask for reduced motion. A pause button is shown while autoplay is on.", "default": true },
    {
      "type": "range",
      "id": "autoplay_speed",
      "label": "Change slides every",
      "min": 3,
      "max": 12,
      "step": 1,
      "unit": "s",
      "default": 6,
      "visible_if": "{{ section.settings.autoplay }}"
    },
    {
      "type": "checkbox",
      "id": "pause_on_hover",
      "label": "Pause on hover and keyboard focus",
      "default": true,
      "visible_if": "{{ section.settings.autoplay }}"
    },
    { "type": "checkbox", "id": "loop", "label": "Loop back to the first slide", "default": true },
    { "type": "checkbox", "id": "show_arrows", "label": "Show arrows", "default": true },
    {
      "type": "select",
      "id": "pagination",
      "label": "Slide indicators",
      "options": [
        { "value": "dots", "label": "Dots" },
        { "value": "progress", "label": "Progress bars" },
        { "value": "none", "label": "None" }
      ],
      "default": "progress"
    },

    { "type": "header", "content": "Layout" },
    {
      "type": "select",
      "id": "height",
      "label": "Height on desktop",
      "options": [
        { "value": "small", "label": "Small" },
        { "value": "medium", "label": "Medium" },
        { "value": "large", "label": "Large" },
        { "value": "full", "label": "Full screen" },
        { "value": "adapt", "label": "Adapt to first image" }
      ],
      "default": "large"
    },
    {
      "type": "select",
      "id": "height_mobile",
      "label": "Height on mobile",
      "options": [
        { "value": "small", "label": "Small" },
        { "value": "medium", "label": "Medium" },
        { "value": "large", "label": "Large" },
        { "value": "full", "label": "Full screen" },
        { "value": "adapt", "label": "Adapt to first image" }
      ],
      "default": "large"
    },
    {
      "type": "select",
      "id": "section_width",
      "label": "Width",
      "options": [
        { "value": "full", "label": "Full width" },
        { "value": "page", "label": "Page width" }
      ],
      "default": "full"
    },
    {
      "type": "range",
      "id": "corner_radius",
      "label": "Corner radius",
      "min": 0,
      "max": 40,
      "step": 2,
      "unit": "px",
      "default": 16,
      "visible_if": "{{ section.settings.section_width == 'page' }}"
    },
    { "type": "range", "id": "content_width", "label": "Content max width", "min": 320, "max": 960, "step": 20, "unit": "px", "default": 620 },

    { "type": "header", "content": "Colors" },
    { "type": "color", "id": "color_bg", "label": "Background", "info": "Shows around the slideshow when it has padding or page width.", "default": "#F5EFE6" },
    { "type": "color_background", "id": "color_bg_gradient", "label": "Background gradient", "info": "Optional. Covers the background color." },
    { "type": "color", "id": "color_accent", "label": "Solid button", "default": "#FFFFFF" },
    { "type": "color", "id": "color_accent_text", "label": "Text on solid button", "default": "#1C1917" },
    { "type": "color", "id": "color_controls", "label": "Arrows and indicators", "default": "#FFFFFF" },

    { "type": "header", "content": "Spacing and visibility" },
    { "type": "range", "id": "padding_top", "label": "Top padding on desktop", "min": 0, "max": 200, "step": 4, "unit": "px", "default": 0 },
    { "type": "range", "id": "padding_bottom", "label": "Bottom padding on desktop", "min": 0, "max": 200, "step": 4, "unit": "px", "default": 0 },
    { "type": "range", "id": "padding_top_mobile", "label": "Top padding on mobile", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 0 },
    { "type": "range", "id": "padding_bottom_mobile", "label": "Bottom padding on mobile", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 0 },
    {
      "type": "select",
      "id": "show_on",
      "label": "Show on",
      "options": [
        { "value": "all", "label": "All devices" },
        { "value": "desktop", "label": "Desktop only" },
        { "value": "mobile", "label": "Mobile only" }
      ],
      "default": "all"
    },
    { "type": "text", "id": "anchor_id", "label": "Anchor ID", "info": "Optional. Link to this section with #your-id." },

    { "type": "header", "content": "Motion" },
    { "type": "checkbox", "id": "animate", "label": "Animate text when a slide appears", "default": true }
  ],
  "blocks": [
    {
      "type": "slide",
      "name": "Slide",
      "settings": [
        { "type": "header", "content": "Content" },
        { "type": "text", "id": "eyebrow", "label": "Eyebrow", "default": "New season" },
        { "type": "inline_richtext", "id": "heading", "label": "Heading", "default": "Made for long tables" },
        { "type": "richtext", "id": "text", "label": "Text", "default": "<p>Stoneware, linen and candlelight for evenings that run late.</p>" },

        { "type": "header", "content": "Image" },
        { "type": "image_picker", "id": "image", "label": "Desktop image", "info": "A wide image works best, at least 2000px across." },
        { "type": "image_picker", "id": "image_mobile", "label": "Mobile image", "info": "Optional. Shown below 750px; a portrait crop works best." },
        { "type": "color", "id": "overlay_color", "label": "Overlay color", "default": "#1C1917" },
        { "type": "range", "id": "overlay_opacity", "label": "Overlay opacity", "min": 0, "max": 90, "step": 5, "unit": "%", "default": 30 },

        { "type": "header", "content": "Button" },
        { "type": "text", "id": "button_label", "label": "Button label", "default": "Shop tableware" },
        { "type": "url", "id": "button_url", "label": "Button link" },
        {
          "type": "select",
          "id": "button_style",
          "label": "Button style",
          "options": [
            { "value": "primary", "label": "Solid" },
            { "value": "outline", "label": "Outline" },
            { "value": "text", "label": "Text link" }
          ],
          "default": "primary"
        },
        { "type": "checkbox", "id": "button_new_tab", "label": "Open link in a new tab", "default": false },
        {
          "type": "url",
          "id": "slide_url",
          "label": "Whole slide link",
          "info": "Used only when the button label is empty: the entire slide becomes one link."
        },

        { "type": "header", "content": "Layout" },
        {
          "type": "select",
          "id": "content_position",
          "label": "Content position on desktop",
          "options": [
            { "value": "top-left", "label": "Top left" },
            { "value": "top-center", "label": "Top center" },
            { "value": "top-right", "label": "Top right" },
            { "value": "middle-left", "label": "Middle left" },
            { "value": "middle-center", "label": "Middle center" },
            { "value": "middle-right", "label": "Middle right" },
            { "value": "bottom-left", "label": "Bottom left" },
            { "value": "bottom-center", "label": "Bottom center" },
            { "value": "bottom-right", "label": "Bottom right" }
          ],
          "default": "middle-left"
        },
        { "type": "text_alignment", "id": "text_alignment", "label": "Text alignment on desktop", "default": "left" },
        {
          "type": "select",
          "id": "content_position_mobile",
          "label": "Content position on mobile",
          "options": [
            { "value": "top", "label": "Top" },
            { "value": "middle", "label": "Middle" },
            { "value": "bottom", "label": "Bottom" }
          ],
          "default": "bottom"
        },
        {
          "type": "select",
          "id": "text_alignment_mobile",
          "label": "Text alignment on mobile",
          "options": [
            { "value": "left", "label": "Left" },
            { "value": "center", "label": "Center" },
            { "value": "right", "label": "Right" }
          ],
          "default": "left"
        },

        { "type": "header", "content": "Colors" },
        { "type": "color", "id": "color_text", "label": "Text", "default": "#FFFFFF" }
      ]
    }
  ],
  "presets": [
    {
      "name": "Lib · Hero slideshow",
      "blocks": [
        {
          "type": "slide",
          "settings": {
            "eyebrow": "New season",
            "heading": "Made for <em>long</em> tables",
            "text": "<p>Sand-glazed stoneware, washed linen and beeswax candles for evenings that run late.</p>",
            "button_label": "Shop tableware",
            "content_position": "middle-left"
          }
        },
        {
          "type": "slide",
          "settings": {
            "eyebrow": "Bedroom",
            "heading": "Linen that softens with every wash",
            "text": "<p>Stonewashed bedding in oat, clay and undyed flax.</p>",
            "button_label": "Shop bedding",
            "content_position": "bottom-center",
            "text_alignment": "center",
            "text_alignment_mobile": "center",
            "overlay_opacity": 35
          }
        },
        {
          "type": "slide",
          "settings": {
            "eyebrow": "Kitchen",
            "heading": "Thrown by hand, used every day",
            "text": "<p>Speckled mugs and bowls, made in small batches.</p>",
            "button_label": "Shop the kitchen",
            "content_position": "middle-right",
            "overlay_opacity": 25
          }
        }
      ]
    }
  ]
}
{% endschema %}
```

### snippets/lib-image.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{% doc %}
  Responsive image with optional art direction: a separate mobile image (below 750px),
  each honouring its own focal point from the theme editor. Falls back to a placeholder.

  @param {image} [image] - Desktop image (also used on mobile when no mobile image is set)
  @param {image} [image_mobile] - Mobile image, below 750px
  @param {string} [class] - Class for the img element
  @param {string} [sizes] - sizes attribute for the desktop image (default 100vw)
  @param {boolean} [eager] - Load immediately with high fetch priority (use for the first sections on a page)
  @param {string} [placeholder] - placeholder_svg_tag name when no image is set (default 'lifestyle-1')

  @example
  {% render 'lib-image', image: section.settings.image, image_mobile: section.settings.image_mobile, class: 'lib-hero__img', sizes: '(min-width: 990px) 50vw, 100vw', eager: true %}
{% enddoc %}

{%- liquid
  assign desktop = image
  if desktop == blank
    assign desktop = image_mobile
  endif
  assign img_sizes = sizes | default: '100vw'
  assign img_loading = 'lazy'
  assign img_priority = 'auto'
  if eager
    assign img_loading = 'eager'
    assign img_priority = 'high'
  endif
  assign art = false
  if image != blank and image_mobile != blank
    assign art = true
  endif
-%}

{%- if desktop != blank -%}
  <picture
    class="lib-picture{% if art %} lib-picture--art{% endif %}"
    {% if art %}
      style="--lib-pos-m: {{ image_mobile.presentation.focal_point | default: '50% 50%' }};"
    {% endif %}
  >
    {%- if art -%}
      <source
        media="(max-width: 749px)"
        srcset="
          {{ image_mobile | image_url: width: 375 }} 375w,
          {{ image_mobile | image_url: width: 750 }} 750w,
          {{ image_mobile | image_url: width: 1100 }} 1100w,
          {{ image_mobile | image_url: width: 1500 }} 1500w
        "
        sizes="100vw"
        width="{{ image_mobile.width }}"
        height="{{ image_mobile.height }}"
      >
    {%- endif -%}
    {{
      desktop
      | image_url: width: 2400
      | image_tag:
        class: class,
        loading: img_loading,
        fetchpriority: img_priority,
        sizes: img_sizes,
        widths: '600, 900, 1200, 1600, 2000, 2400'
    }}
  </picture>
{%- else -%}
  {{ placeholder | default: 'lifestyle-1' | placeholder_svg_tag: class }}
{%- endif -%}

{% stylesheet %}
  .lib-picture { display: contents; }
  @media (max-width: 749px) {
    /* image_tag sets the desktop focal point inline; the mobile image needs its own. */
    .lib-picture--art img { object-position: var(--lib-pos-m) !important; }
  }
{% endstylesheet %}
```

### snippets/lib-button.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{% doc %}
  Animated call-to-action link. Light sweep on hover, arrow slides right.
  Colors come from the parent section's --lib-accent / --lib-accent-text / --lib-text vars.
  Inspired by Uiverse.io button patterns; rewritten for themes, no dependencies.

  @param {string} label - Button text
  @param {string} [url] - Link target; renders a disabled-looking span when blank
  @param {string} [style] - 'primary' (default), 'outline' or 'text'
  @param {boolean} [new_tab] - Open the link in a new tab
  @param {boolean} [arrow] - Show the trailing arrow (default true)

  @example
  {% render 'lib-button', label: section.settings.button_label, url: section.settings.button_url, style: 'outline' %}
{% enddoc %}

{%- liquid
  assign btn_style = style | default: 'primary'
  assign show_arrow = true
  if arrow == false
    assign show_arrow = false
  endif
-%}

{%- unless label == blank -%}
{%- capture inner -%}
  <span class="lib-btn__label">{{ label | escape }}</span>
  {%- if show_arrow -%}
    <svg class="lib-btn__arrow" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" focusable="false">
      <path d="M3 8h9M8.5 4.5 12 8l-3.5 3.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
    </svg>
  {%- endif -%}
{%- endcapture -%}

{%- if url != blank -%}
  <a
    class="lib-btn lib-btn--{{ btn_style }}"
    href="{{ url }}"
    {% if new_tab %}
      target="_blank" rel="noopener"
    {% endif %}
  >
    {{- inner -}}
  </a>
{%- else -%}
  <span class="lib-btn lib-btn--{{ btn_style }}" aria-disabled="true">{{ inner }}</span>
{%- endif -%}
{%- endunless -%}

{% stylesheet %}
  .lib-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    padding: 0.85em 1.5em;
    border-radius: var(--lib-radius, 999px);
    font: inherit;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    overflow: hidden;
    isolation: isolate;
    transition: transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
  }
  .lib-btn--primary {
    background: var(--lib-accent, #111);
    color: var(--lib-accent-text, #fff);
    box-shadow: 0 1px 2px rgb(0 0 0 / 0.12);
  }
  .lib-btn--outline {
    background: transparent;
    color: var(--lib-text, #111);
    box-shadow: inset 0 0 0 1.5px currentColor;
  }
  .lib-btn--text {
    padding-inline: 0;
    background: none;
    color: var(--lib-text, #111);
    text-decoration: underline;
    text-underline-offset: 0.3em;
    overflow: visible;
  }
  .lib-btn--text::before { display: none; }
  .lib-btn--text:hover { transform: none; box-shadow: none; }
  .lib-btn::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(110deg, transparent 30%, rgb(255 255 255 / 0.35) 50%, transparent 70%);
    transform: translateX(-120%);
    transition: transform 0.6s ease;
  }
  .lib-btn--outline::before {
    background: linear-gradient(110deg, transparent 30%, rgb(127 127 127 / 0.18) 50%, transparent 70%);
  }
  .lib-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px -8px rgb(0 0 0 / 0.35);
  }
  .lib-btn:hover::before { transform: translateX(120%); }
  .lib-btn__arrow { transition: transform 0.2s ease; }
  .lib-btn:hover .lib-btn__arrow { transform: translateX(3px); }
  .lib-btn:focus-visible {
    outline: 2px solid var(--lib-accent, #111);
    outline-offset: 3px;
  }
  .lib-btn[aria-disabled='true'] { pointer-events: none; }
  @media (prefers-reduced-motion: reduce) {
    .lib-btn, .lib-btn::before, .lib-btn__arrow { transition: none; }
    .lib-btn:hover { transform: none; }
  }
{% endstylesheet %}
```

## Lisans

MIT Lisansı, © 2026 Lintel. Kendi mağazanızda ya da müşteri işlerinde ücretsiz kullanabilir, değiştirebilir ve yayınlayabilirsiniz; her dosyanın başındaki lisans satırını koruyun.
